hdu1257 dp(最长上升子序列)

时间:2021-12-27 17:02:43

题意:有一种拦截系统,可以打击导弹,但是打击的高度会逐渐下降,因此为了防御导弹攻击,就必须用多个系统,现给出一列导弹依次的高度,求最少需要的系统数。

这道题是最长上升子序列问题,但是我一开始其实并没有想到,最开始我的思路是依次剔除最长下降子序列,每剔除一轮就是需要一个拦截系统,然后直到全部数都剔除了就可以知道要几个拦截系统了。而且这样做就是最长下降子序列符合 dp 的思路也可以自圆其说,所以说为什么我成长得这么慢,其实就是我刷 dp 专题就使劲往怎么用 dp 上想而不是怎么做出来上想,很多时候这样其实我的进步还是太小。

恩,这样做 WA 了,我也不是很清楚为什么 WA ,但是我在这么敲的时候就觉得这种思路其实很乱,就这么 A 了其实对我也不太好吧。

WA 了就知道要找新办法了,于是我想到了另一种做法,边遍历数字边建系统,对于一个数字,如果之前建立过的系统中有最小值大于这个数字的,那么就说明那个系统可以拦截这枚导弹,那么就把该拦截系统的最小值改为这个数字,而如果这个数字大于所有之前拦截系统的最小值的话,那就说明没有系统可以拦截这枚导弹了,我就重新建立一个系统,其最小值就是当前数字。其实我并不知道到底是不是对的,因为有一点需要考虑,当有很多系统都能拦截它时,我该优化哪一个呢,我选择了最小的,显然我也不知道这样对不对。然后我 A 了```不甘心地 A 了```

问过学长之后,学长告诉我,其实就只是一个最长上升子序列。细想一下,对于这个最长上升子序列而言,每一个数代表一个拦截系统的最小值,并且由于序列是上升的,每一个数都不能再拦截序列中的下一个数,因为下一个数更大,因此这个子序列的长度就是拦截系统数。我觉得这个说法我更能接受,或许之前那个做法只是因为数据弱所以就这么过了吧```

就这样,我感觉我和数据一样弱```

蠢,就是蠢!

 #include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[],a[];
int main(){
int n;
while(scanf("%d",&n)!=EOF){
int i,j,c=;
memset(dp,,sizeof(dp));
for(i=;i<=n;i++){
scanf("%d",&a[i]);
int f=;
for(j=;j<=c;j++){
if(a[i]<dp[j]){
f=;
dp[j]=a[i];
break;
}
}
if(!f)dp[++c]=a[i];
sort(dp+,dp+c+);
}
printf("%d\n",c);
}
return ;
}