简单的动态规划问题总览(图)

图等晚上画完再发……

简单的动态规划问题主要包括两个部分,第一个线性动态规划等等,第二个就是简单的动态规划问题(见另一篇博客)。

这篇博客主要讲线性动态规划。

最最经典的问题就是求最长不下降子序列,例如一本通P270-P282页内容,例题全部都是最长不下降子序列的变种。

最长不下降子序列的基本思路是:

  处理第某位元素,查找它可以连接到的长度最大的最长不下降序列,也就是搜索它之前的所有元素,找到能够跟它连接的元素(也就是比它小的),然后在找到的元素里找出连接有最长的序列的那一个,然后连接。搜索完毕整个序列后,整个序列里长度最大的值就是所求的最长不下降序列的长度。

OK,上例题 (都是标准的求最长不下降序列问题,模板可直接过):

  (1) 洛谷【P1020】导弹拦截  :

#include<iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
  //freopen("1.txt","r",stdin);
  int j,k,x;
  int a[10000],b[10000],h[10000];
  int i=1,n=0,m=0;
  while (cin>>a[i]) {
    int maxx=0;
    for(j=1;j<=i-1;j++){
      if(a[j]>=a[i]) if(b[j]>maxx) maxx = b[j];}
      b[i] = maxx+1;
      if(b[i]>m) m=b[i];
      x=0;
      for(k=1;k<=n;k++){
        if(h[k]>=a[i]){
          if(x==0) x=k;
          else if(h[k]<h[x]) x=k;
       }
      }
      if(x==0){n++;x=n;}
      h[x] = a[i];i++;
  }
  cout<<m<<endl<<n<<endl;
}

  (2)洛谷 【P1091】合唱队形

#include<iostream>
#include<cstdio>
using namespace std;
int a[1000],b[1000],c[1000];
int main(){
  int n,maxx;
  cin>>n;
  for(int i=1;i<=n;i++){
    cin>>a[i];
  }
  for(int i =1;i<=n;i++){
    b[i] = 1;
    for(int j=1;j<=i-1;j++){
      if((a[i]>a[j])&&b[j]+1>b[i]){
        b[i]=b[j]+1;
      }
    }
  }
  for(int i=n;i>=1;i--){
    c[i]=1;
    for(int j=i+1;j<=n;j++){
      if((a[j]<a[i])&&(c[j]+1>c[i])) c[i] = c[j]+1;
    }
  }
  maxx=0;
  for(int i=1;i<=n;i++){
    if(b[i]+c[i]>maxx){
      maxx=b[i]+c[i];
    }
  }
  cout<<n-maxx+1;
}

  

原文地址:https://www.cnblogs.com/zhangone/p/5579527.html