hdu--DP(必须掌握)

来源:互联网 发布:巴特尔cba数据 编辑:程序博客网 时间:2024/05/01 09:45

 

 

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


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


/*
//1421 搬寝室

#include <stdio.h> #include <stdlib.h> #define size 2005 #define INIT 2147483646int 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};//保存最长子序列,第一个是1
int 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; }
 
 
出处:
http://www.cnblogs.com/syxchina/archive/2010/08/16/2197372.html