zoukankan      html  css  js  c++  java
  • 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};//保存最长子序列,第一个是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;
    }

    */

    作者:BuildNewApp
    出处:http://syxchina.cnblogs.comBuildNewApp.com
    本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
    如果您阅读了我的文章并觉得有价值请点击此处,谢谢您的肯定1。
  • 相关阅读:
    洛谷P2062 分队问题
    bzoj1800 飞行棋
    UVA11100 The Trip, 2007
    UVA11134 Fabled Rooks
    每天一道博弈论之“威佐夫博弈”
    每天一道博弈论之“A game”(伪博弈
    每天一道博弈论之“谁能赢呢?”
    每天一道博弈论之“牛的数字游戏”
    每天一道博弈论之“E&D”
    每天一道博弈论之“巴什博弈”
  • 原文地址:https://www.cnblogs.com/syxchina/p/2197372.html
Copyright © 2011-2022 走看看