題目來源於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;
}