动态规划实例

HDU中的DP---动态规划

 

//Made by syx //Time 2010年8月15日 10:13:12 // //

小结:DP的基本思想 如果各个子问题不是独立的,不同的子问题的个数只是多项式量级, 如果我们能够保存已经解决的子问题的答案,而在需要的时候再找 出已求得的答案,这样就可以避免大量的重复计算。    由此而来的基本思路是——用一个表记录所有已解决的子 问题的答案,不管该问题以后是否被用到,只要它被计算过,就将 其结果填入表中。

/* //1421 搬寝室

复制代码
#include <stdio.h>  #include <stdlib.h>  #define size 2005  #define INIT 2147483646
int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; }
int Min(int a,int b) { return a<b?a:b; }
int dp[size][1005];
int main() { int n,k,i,j; int val[size] = {0}; dp[0][0] = 0; while (scanf("%d%d",&n,&k)!=EOF) { val[0] = 0; for(i=1;i<=n;i++) scanf("%d",&val[i]); qsort(val+1,n,sizeof(val[0]),cmp); for (i=0;i<=n;i++) { for(j=1;j<=k;j++) dp[i][j] = INIT; } for (i=2;i<=n;i++) { for (j=1;j*2<=i;j++) dp[i][j] = Min(dp[i-2][j-1]+(val[i]-val[i-1])*(val[i]-val[i-1]),dp[i-1][j]); } printf("%d\n",dp[n][k]); } return 0; }
复制代码

*/

/* //1159 //最长公共子序列问题

复制代码
#include <iostream> #include <string> using namespace std; int max(int a,int b) { return a >= b ? a : b; }
int a[1000][1000]; int main() { int i , j; //int a[1000][1000];string s1,s2; while(cin>>s1>>s2) { memset(a[0],0,100); for(i=0; i<s1.length(); i++) for(j=0; j<s2.length(); j++) { if(s1[i] == s2[j] ) a[i+1][j+1] = a[i-1+1][j-1+1] + 1; else a[i+1][j+1] = max(a[i-1+1][j+1] , a[i+1][j-1+1]); } cout<<a[s1.length()][s2.length()]<<endl; } return 0; }
复制代码

*/

/* //1087 //题目就是求在一个有序的序列(从小到大)中求一个和最大的序列,所以 //也是最长序列的扩展 //

复制代码
#include<iostream> #include <algorithm> using namespace std; int dp[1001]; int num[1001]; int max(int a,int b) { return a>=b?a:b; } int main() { int i,j,n;     for(;cin>>n&&n;)     {         memset(dp,0,sizeof dp);         for( i=1;i<=n;i++)         {             cin>>num[i];         }         int maxdp=0;         for( i=1;i<=n;i++)             for( j=0;j<i;j++)                 if(num[i]>num[j])                 {                     dp[i]=max(dp[i],dp[j]+num[i]);                     if(dp[i]>maxdp)                         maxdp=dp[i];                 }    cout<<maxdp<<endl;     } return 0; }
复制代码

*/

/* //1160 //题目大意:所有的老鼠都有一个重量(W) 和一个速度(S),要求找出满足以下关系的最长序列 //W[m[1]] < W[m[2]] < ... < W[m[n]] //and //S[m[1]] > S[m[2]] > ... > S[m[n]] //因为是一个二维的关系,处理起来比较麻烦,所以,我们可以先选择对重量进行从小到大排序(也可以选速度),这样,就只需找出以为上的最长上升子序列了。 //状态转移方程 //    if (a[j].s>a[i].s && m[j]+1>m[i]) //    { //     m[i]=m[j]+1; //     pre[i]=j; //    } //不过题目最后要的输出是最长上升子序列的长度 以及该子序列选取的所有老鼠的编号(从1开始的) //刚开始怎么调试,得出的答案都和Sample Output不是很一样,郁闷了很久

复制代码
#include <stdio.h> #include <stdlib.h> struct No { int w; int s; int num; }a[1005]; int cmp(const void *c,const void *d) { return *(int *)c-*(int *)d; } int main () { int n=0,i,j,k,max; int m[1005],pre[1005],p[1005]; while (scanf("%d %d",&a[n].w,&a[n].s)!=EOF) {    a[n].num=n+1;    n++; } qsort(a,n,sizeof(a[0]),cmp); for (i=0;i<n;i++) {    m[i]=1;pre[i]=-1;    for (j=i-1;j>=0;j--)    {     if (a[j].s>a[i].s && m[j]+1>m[i])     {      m[i]=m[j]+1;      pre[i]=j;     }    } } for (max=0,i=0;i<n;i++)    if (m[i]>m[max]) max=i; printf("%d\n",m[max]); k=0; while (pre[max]!=-1) {    p[k++]=a[max].num;    max=pre[max]; } p[k++]=a[max].num; while (k--)    printf ("%d\n",p[k]); return 0; }
复制代码

*/

/* //1160

复制代码
#include <stdio.h>  #include <iostream>  #include <algorithm>  #include <stack>  #define MAX 1000  using namespace std;  struct Mouse  {      int W;      int S;      int L;  };  Mouse mouse[MAX+10];  int flag[MAX+10];  int f[MAX+10];  bool cmp(const Mouse a,const Mouse b)  {      if(a.W==b.W)    return a.S>b.S;      return a.W<b.W;  }  int main()  {      int i(1),j,n,w,s;     stack<int> stk;     f[1]=1;      flag[1]=1;      while(scanf("%d%d",&w,&s)!=EOF)      {          mouse[i].W=w;          mouse[i].S=s;          mouse[i].L=i;          i++;      }      n=i;      sort(mouse+1,mouse+n,cmp);      for(i=2;i<n;i++)      {          int temp(0);          for(j=1;j<i;j++)          {              if(mouse[j].W<mouse[i].W&&mouse[j].S>mouse[i].S&&f[j]>temp)      {       temp=f[j];       flag[i]=j;      }      f[i]=temp+1;          }      }      int max=-1,maxi;      for(i=1;i<n;i++)          if(max<f[i])          {              max=f[i];              maxi=i;     }  printf("%d\n",max);  for(i=0;i<max;i++)  {     int j=maxi;     stk.push(mouse[j].L);     maxi=flag[j];  }  while(!stk.empty())  {     printf("%d\n",stk.top());     stk.pop();  }  return 0;  } 
复制代码

*/

/* //最长有序子序列

复制代码
#include <stdio.h> int main() { int a[9] = {1,4,7,2,5,8,3,6,9}; int f[9] = {1};//保存最长子序列,第一个是1int i,j; for(i=1; i<9; i++) {    for(j=i-1; j>=0; j--)    {     if(a[i]>=a[j])     {      f[i] = f[j] + 1;      break;     }    } } for(i=0; i<9; i++) {    printf("%d ",f[i]); } return 0; }
复制代码

*/ /* //数塔问题

复制代码
#include <iostream>  #define maxn 100  using namespace std;  int max(int a,int b)  {  return (a>b?a:b);  }  int main()  {  int a[maxn+1][maxn+1],i,j,n;  cin >>n;  for (i=1;i<=n;i++)    for (j=1;j<=i;j++)      cin >>a[i][j];  for (i=n-1;i>=1;i--)    for (j=1;j<=i;j++)      a[i][j]+=max(a[i+1][j],a[i+1][j+1]);  cout <<a[1][1]<<endl;  return 0;  }
复制代码

*/

posted @ 2013-08-02 09:04  平林新袖  阅读(339)  评论(0编辑  收藏  举报