1044 拦截导弹——http://codevs.cn/problem/1044/
第一部分:題目
題目描述?Description? ? 某國為了防御敵國的導(dǎo)彈襲擊,發(fā)展出一種導(dǎo)彈攔截系統(tǒng)。但是這種導(dǎo)彈攔截系統(tǒng)有一個缺陷:雖然它的第一發(fā)炮彈能夠到達(dá)任意的高度,但是以后每一發(fā)炮彈都不能高于前一發(fā)的高度。某天,雷達(dá)捕捉到敵國的導(dǎo)彈來襲。由于該系統(tǒng)還在試用階段,所以只有一套系統(tǒng),因此有可能不能攔截所有的導(dǎo)彈。
??
輸入描述?Input Description輸入導(dǎo)彈依次飛來的高度(雷達(dá)給出的高度數(shù)據(jù)是不大于30000的正整數(shù))
??
輸出描述?Output Description輸出這套系統(tǒng)最多能攔截多少導(dǎo)彈,如果要攔截所有導(dǎo)彈最少要配備多少套這種導(dǎo)彈攔截系統(tǒng)。
樣例輸入?Sample Input389 207 155 300 299 170 158 65?
樣例輸出?Sample Output6
2
數(shù)據(jù)范圍及提示?Data Size & Hint導(dǎo)彈的高度<=30000,導(dǎo)彈個數(shù)<=20
第二部分:思路
需要解決兩個問題:1,一套系統(tǒng)最多攔截多少導(dǎo)彈?2,要攔截所有導(dǎo)彈最少需要多少系統(tǒng)?
問題1:動態(tài)規(guī)劃:主要是確定攔截哪些導(dǎo)彈。也就是求數(shù)列中的最長遞減序列。從最后一個數(shù)開始,統(tǒng)計以每個數(shù)為首的遞減序列的長度,取最長的即可。
問題2:貪心:就是盡可能每次攔截最多導(dǎo)彈。可以看出就是每次把問題1的結(jié)果即最長序列中的導(dǎo)彈全攔截了,直到所有導(dǎo)彈都被攔截為止。這里怎么表示導(dǎo)彈被攔截了呢:把被攔截的導(dǎo)彈的遞減序列長度置為0即可。然后需要從新進(jìn)行遞減序列長度計算。
第三部分:代碼
#include<stdio.h> int s[20][2],len=0;//存儲導(dǎo)彈高度及以其為首的最長遞減序列長度 int acount()//計算遞減序列長度并返回最大值 {int Max=0,j,i;for(i=len-2;i>=0;i--)//從最后一個數(shù)開始計算 {int max=0;for(j=i+1;j<len;j++){//注意:s[j][1]該值為0表示導(dǎo)彈被攔截了,就pass。 if(s[j][1]>0&&s[i][0]>s[j][0]&&max<s[j][1]) {max=s[j][1];}}if(s[i][1]>0){s[i][1]=max+1;}if(Max<s[i][1])//尋找最大值 {Max=s[i][1];}}return Max; } int main() {int height;while(scanf("%d",&height)!=EOF){s[len][0]=height;s[len++][1]=1;//初始化每個導(dǎo)彈的最長遞減序列長度為1 }int i,j;int Max=acount();//第一次系統(tǒng)能夠攔截導(dǎo)彈最大值 int max=acount();//每次能夠攔截最大值 int count=0;//統(tǒng)計需要至少多少系統(tǒng) while(max>0)//當(dāng)前有導(dǎo)彈未被攔截就進(jìn)行攔截操作 {count++;//每次攔截的都是攔截最多導(dǎo)彈:可以想象,依次攔截的導(dǎo)彈的序列長度//是遞減的。 for(i=0;i<len;i++){if(s[i][1]==max&&max>0){s[i][1]=0;max--;}if(max==0)//當(dāng)前攔截結(jié)束 {break;}}max=acount();//需要重新計算序列長度以及當(dāng)前剩下所有導(dǎo)彈的最長遞減序列 }printf("%d\n%d\n",Max,count);return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/xiangguoguo/p/5386544.html
總結(jié)
以上是生活随笔為你收集整理的1044 拦截导弹——http://codevs.cn/problem/1044/的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle database serv
- 下一篇: Atitit.atiJsBridge 新