题意:如题。
这道题目可以用贪心和动态规划求解,其实两种方法都是想通的。
贪心思想:对于每个飞来的导弹,查找能够打到它的,飞得最低的防御系统,如果没有,则加入一个新防御系统。
动态规划思想:就是求最长上升子序列。
贪心方法:
#include <iostream>
using namespace std;
int dp[100000],num[100000],heigh[100000];
int DP(int n)
{
int i,j;
int pos,min,Count,Max;
Count=1;
heigh[0]=0;
for(i=0;i<n;i++)
{
for(j=0;j<Count;j++)
{
if(num[i]<=heigh[j])
{
heigh[j]=num[i];
break;
}
if(num[i]>heigh[j] && j==Count-1)
{
heigh[Count++]=num[i];
}
}
}
return Count-1;
}
int main()
{
int i,n;
while(cin>>n)
{
for(i=0;i<n;i++)
{
cin>>num[i];
dp[i]=1;
}
cout<<DP(n)<<endl;
}
}
会发现,贪心方法的思想和动态规划方法的思想是一样的。
上面代码求的其实是最长上升子序列。
如果对比求最长上升子序列的O(nlogn)复杂度的贪心算法+二分法,会发现上面的贪心思想其实就是求最长上升子序列的O(nlogn)复杂度的贪心算法+二分法的思想中的二分法换成了线性查找,也就是说,上面的贪心思想其实就是求最长上升子序列。
所以这道题目可以用动态规划来求最长上升子序列。
#include <cstdio>
#include <cstring>
int H[40000], F[40000];
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main()
{
int n, i, j, max;
while (scanf("%d", &n) != EOF)
{
for (i = 0; i < n; ++i)
scanf("%d", H+i);
max = F[0] = 1;
for (i = 1; i < n; ++i)
{
F[i] = 1;
for (j = 0; j < i; ++j)
{
if (H[j] < H[i] && F[i] < F[j] + 1)
F[i] = F[j] + 1;
}
max = MAX(max, F[i]);
}
printf("%d\n", max);
}
return 0;
}