序列型动态规划

来源:互联网 发布:巨人网络私有化进程 编辑:程序博客网 时间:2024/04/29 08:52

题目来源于codevs
序列型动态规划最经典的就是LIS 和LCS了

我们来看些题目
1044 拦截导弹
题目描述 Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入描述 Input Description
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)

输出描述 Output Description
输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
样例输入 Sample Input
389 207 155 300 299 170 158 65
样例输出 Sample Output
6
2
分析:
最多能拦截多少,由题意很明显就是最长不上升子序列了
然后需要多少套,那么也就是看最长上升子序列了。

#include<cstdio>#include<cmath>#include<iostream>using namespace std;int main() { int rd[50]; int up[50],down[50];//  int k=1,ans=-1,need=-1; while(scanf("%d",&rd[k])!=EOF) {  k++; } k=k-1; for(int i=1;i<=k;i++)  {   up[i]=1;   down[i]=1;      for(int j=1;j<i;j++)  {   if(rd[i]<=rd[j] && up[i]<up[j]+1)up[i]=up[j]+1;   if(rd[i]>rd[j] && down[i]<down[j]+1)down[i]=down[j]+1;  }   ans=max(ans,up[i]);   need=max(need,down[i]);     }printf("%d\n",ans);printf("%d\n",need);return 0;}

1576 最长严格上升子序列
题目描述 Description
给一个数组a1, a2 … an,找到最长的上升降子序列ab1

#include<cstdio>#include<cmath>#include<iostream>using namespace std;int main() { int rd[5000+5],down[5000+5]; int k,ans=-1; scanf("%d",&k); for(int i=1;i<=k;i++ ) scanf("%d",&rd[i]); for(int i=1;i<=k;i++)  {   down[i]=1;      for(int j=1;j<i;j++)  {if(rd[i]>rd[j] && down[i]<down[j]+1)down[i]=down[j]+1;  }  ans=max(ans,down[i]);  } printf("%d",ans); return 0;}

3027 线段覆盖 2
题目描述 Description
数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。

n<=1000

输入描述 Input Description
第一行一个整数n,表示有多少条线段。

接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci。

输出描述 Output Description
输出能够获得的最大价值
样例输入 Sample Input
3
1 2 1
2 3 2
1 3 4
样例输出 Sample Output
4
分析:
前两题完全就是LIS 的直接运用。
然后这道题,首先我们可以将读入的线段按终点进行排序。
如果某边的起点大于等于另一边的终点则一定不会重合。

#include<cstdio>#include <iostream>#include<algorithm>using namespace std;struct line{int a,b,v;}li[1005];int cmp(const line x,const line y){ return x.b<y.b;}int main(){ int n;  scanf("%d",&n);  for(int i=0;i<n;i++)  {scanf("%d",&li[i].a);   scanf("%d",&li[i].b);   scanf("%d",&li[i].v);  }  sort(li,li+n,cmp);  int maxn=0;  for(int i=0;i<n;i++)  { int k=0;     for(int j=0;j<i;j++)       { if(li[i].a>=li[j].b)           {           if(k<li[j].v);              k=li[j].v;           }       }    li[i].v=li[i].v+k;    if(maxn<li[i].v)maxn=li[i].v;  }  printf("%d",maxn);return 0;}
0 0
原创粉丝点击