序列型動態規劃

題目來源於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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章