飛彈攔截
某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。
輸入飛彈依次飛來的高度(雷達給出的高度資料是不大於50000的正整數),計算這套系統最多能攔截多少飛彈,如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
輸入格式:
一行,若干個整數(個數少於100000)
輸出格式:
2行,每行乙個整數,第乙個數字表示這套系統最多能攔截多少飛彈,第二個數字表示如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
輸入樣例#1:
複製
389 207 155 300 299 170 158 65
輸出樣例#1:
複製
62
為了讓大家更好地測試n方演算法,本題開啟spj,n方100分,nlogn200分
每點兩問,按問給分
//我是資料加強以後的第一篇題解(這也是我關於單調性的第一篇題解)這篇有紀念性的文章我要發部落格上,不要認為我是複製他人題解
/*資料加強到了100000,你要是想得滿分200,就必須通過單調性來做(想得100的用n^2演算法),而且還要乙個神奇的思想(我無法證明),那就是,求乙個序列裡面最少有多少最長不上公升序列等於求這個序列裡最長上公升序列的長度。我們用f[x]陣列(第一問)來記錄當前長度為x的不上公升序列中最大的結束點(這個運用了貪心的思想),如果當前數小於等於當前的最長不上公升序列的結束點,那麼我們把當前最長的不上公升序列長度加一,把當前數作為這個 不下降序列的結束點,不然我們就用二分查詢(為什麼可以呢?這是因為我們運用了貪心的思/想後能保證長度越大的不上公升序列結束點越小),試著用當前數去更新長度為x的不上公升序列的結束點(又是貪心的思想,只更新長度最長且結束點小於自己的),然後第二問你再反著做就行了(把大於等於改為小於)*/
#include
#include
#include
using
namespace
std;
const
int maxn=100005;
int a[maxn];
int f[maxn];
intmain
() else
}if(l!=0)f[l]=a[i];}}
cout
memset(f,-1,sizeof(f));//這次前面要盡量小了,不然又無法更新
int ans2=0;
for(int i=1;i<=n;i++)
else
}f[l]=a[i];}}
cout
}
2-合唱隊形
n位同學站成一排,**老師要請其中的(n-k)位同學出列,使得剩下的k位同學排成合唱隊形。
合唱隊形是指這樣的一種隊形:設k位同學從左到右依次編號為1,2…,k,他們的身高分別為t1,t2,…,tk, 則他們的身高滿足t1<...ti+1>…>tk(1<=i<=k)。
你的任務是,已知所有n位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。
輸入格式:
輸入檔案chorus.in的第一行是乙個整數n(2<=n<=100),表示同學的總數。第一行有n個整數,用空格分隔,第i個整數ti(130<=ti<=230)是第i位同學的身高(厘公尺)。
輸出格式:
輸出檔案chorus.out包括一行,這一行只包含乙個整數,就是最少需要幾位同學出列。
輸入樣例#1:
複製
8186 186 150 200 160 130 197 220
輸出樣例#1:
複製
4
對於50%的資料,保證有n<=20;
對於全部的資料,保證有n<=100。
發現大家的方法都一樣,即:一遍遞推算出最長上公升子串行,再一遍遞推算出最長下降子串行,再一遍歷維護max求出答案。
我這裡提供乙個新的思路,建立二維陣列a[105][2]。
a[i][0]代表以第i個人為結尾的最長上公升子串行長度。(整個合唱隊形沒有下降)
a[i][1]代表以第i個人為結尾的最長合唱隊形,但至少有乙個人的身高呈下降趨勢(合唱隊形有下降)
顯然,max(a[i][0],a[i][1])代表前i個人的最長合唱隊形。
直接上**:
#include
#include
using
namespace
std;
int a1[105][2];
int height[105];
intmain
() }
for(int i=1;i<=n;i++)
int ans=0;
for(int i=1;i<=n;i++)
cout
0;}
//一道動態規劃題,分成生序列和降序列即可
#include
#include
using
namespace
std;
int num[1010];//每個人的身高
int ans=1;//最後留下的人數
int sum1[1010],sum2[1010];//公升序列和降序列中留下的人數
intmain
() for(int i=1;i<=n;i++)
for(int j=1;jif(num[i]>num[j])//如果i位置的值大於j位置的,這是可以作為上公升子串行
sum1[i]=max(sum1[i],sum1[j]+1);//比較不取i位置和取i位置哪個留下的人多
for(int i=n;i>=1;i--)//最小降序列,反著列舉
for(int j=n;j>i;j--)
if(num[i]>num[j])
sum2[i]=max(sum2[i],sum2[j]+1);
for(int i=1;i<=n;i++)
ans=max(ans,(sum2[i]+sum1[i]-1));//ans是留下的人數,和每一種方案留下的人數比較。減一是中間的人重複計數。
cout
return
0;}
動態規劃2
動態規劃是研究一類最優化問題的方法,在經濟 工程技術 企業管理 工農業生產及軍事等領域中都有廣泛的應用。近年來,在acm icpc中,使用動態規劃 或部分應用動態規劃思維 求解的題不僅常見,而且形式也多種多樣。而在與此相近的各類資訊學競賽中,應用動態規劃解題已經成為一種趨勢,這和動態規劃的優勢不無關...
動態規劃(2)
題目輸入格式 第1行 兩個數字r,c 1 r,c 100 表示矩陣的行列。第2.r 1行 每行c個數,表示這個矩陣。輸出格式 僅一行 輸出1個整數,表示可以滑行的最大長度。樣例輸入 5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 ...
動態規劃2
最長遞增子串行的問題 給定陣列arr,返回arr的最長遞增子串行長度。比如arr 最長遞增子串行為,返回arr的最長遞增子串行長度。比如arr 最長遞增子串行為所以返回這個子串行的長度為5。解決方案 arr 2 1 5 3 6 4 8 9 7 dp 1 1 2 2 3 3 4 5 4 dp i 表示...