zoukankan      html  css  js  c++  java
  • 简单Dp----最长公共子序列,DAG最长路,简单区间DP等

    /*
      uva 111 * 题意: * 顺序有变化的最长公共子序列; * 模板; */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100]; int mu[100]; int Dp[100][100]; int main() { int n,x; scanf("%d", &n); for(int i=1;i<=n;i++) { scanf("%d", &x); mu[x] = i; } while(scanf("%d", &x)!=EOF) { a[x] = 1; for(int i=2;i<=n;i++) { scanf("%d", &x); a[x] = i; } memset(Dp,0, sizeof(Dp) ); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(a[i] == mu[j]) Dp[i][j] = Dp[i-1][j-1] +1; else Dp[i][j] = max(Dp[i-1][j], Dp[i][j-1]); } } printf("%d ",Dp[n][n]); } return 0; }
    /*
     * uva103
     * 题意:
     *        DAG最长路;
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int cube[100][100];
    int G[100][100];
    int Dp[100];
    int pre[100];
    int n,di;
    void Dfs(int u)
    {    
        for(int i=1;i<=n;i++)
        {
            if(i==u)
                continue;
            if( G[u][i]!= -1 )
            {
                if(Dp[i] < Dp[u]+G[u][i])
                {
                    Dp[i] = Dp[u] + G[u][i];
                    pre[i] = u;
                    Dfs(i);
                }
            }
        }
    }
    void print(int u)
    {
        if(pre[u]!=-1)
            print(pre[u]);
        if(pre[u]!= -1)
            printf(" ");
        printf("%d", u);
    }
    int main()
    {
        while(scanf("%d%d", &n,&di)!=EOF)
        {
            for(int i=1;i<=n;i++)
                for(int j=0; j<di; j++)
                    scanf("%d", &cube[i][j]);
            memset(G, -1, sizeof(G));
            memset(pre, -1, sizeof(pre));
            for(int i=1;i<=n;i++)
                sort(cube[i],cube[i]+di);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    if(i==j)
                        continue;
                    int flag =0 ;
                    for(int x =0;x<di;x++)
                        if( cube[i][x] >= cube[j][x])
                        {
                            flag = 1;
                            break;
                        }
                    if( !flag )
                        G[i][j] = 1;
                }
            for(int i=1;i<=n;i++)
                Dp[i] = 1;
            for(int i=1;i<=n;i++)
                Dfs(i);
            int ans =1;
            for(int i=2;i<=n;i++)
            {
                if(Dp[ans] < Dp[i])
                    ans  =i;
            }
            printf("%d
    ", Dp[ans]);
            print(ans);
            printf("
    ");
        }
        return 0;
    }
    /*
     * uva10405
     * 题意:
     *        LCS;
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n1, n2;
    char s1[2005],s2[2005];
    int Dp[2005][2005];
    int LCS()
    {
        memset(Dp, 0, sizeof(Dp));
        for(int i=1;i<=n1; i++)
            for(int j=1; j<=n2; j++)
                if( s1[i] == s2[j] )
                    Dp[i][j] = Dp[i-1][j-1] + 1;
                else
                    Dp[i][j] = max(Dp[i-1][j], Dp[i][j-1]);
        return Dp[n1][n2];
    }
    int main()
    {
        while(gets(s1+1)&& gets(s2+1))
        {
            n1 = strlen(s1+1);
            n2 = strlen(s2+1);
            int ans = LCS();
            printf("%d
    ",ans);
        }
        return 0;
    }
    /*
     * uva10003
     * 区间Dp
     * 题意,给一个序列是要切开的位置,每次切一刀的代价是当前段的全长;
     * 最小代价;
     * 在区间开始和结尾加上0 和全长;
     * 枚举区间 长度、起点;
     * 这里的长度是跨越的要切的位置的个数,不是真正的长度;
     * 对于每一段内,枚举段内分割点,然后Dp出段内最小代价,直到全长;    
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int a[55],len,n;
    int Dp[55][55];
    int INF = 0x3f3f3f3f;
    int main()
    {
        while(scanf("%d", &len )!=EOF && len )
        {
            memset(Dp, 0, sizeof(Dp));
            scanf("%d", &n);
            for(int i=1;i<=n;i++)
                scanf("%d", &a[i]);
            a[0] = 0;
            a[n+1] = len;
            //区间Dp
            //Dp[i][j]表示左闭右开的区间i,j;
            for(int p = 1; p <= n+1 ; p++)
                for(int i = 0; i+p <= n+1 ; i++)
                {
                    int j = i+p;
                    int Min = INF;
                    for(int k=i+1; k<j;k++)
                        Min = min(Min, Dp[i][k]+Dp[k][j]+a[j]-a[i]);
                    if( Min != INF )
                        Dp[i][j] = Min;
                }
            printf("The minimum cutting is %d.
    ",Dp[0][n+1]);
        }
        return 0;
    }
    /*
     * uva116
     * 简单的Dp,前缀最小要倒着DP
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m;
    int a[25][105];
    int Dp[25][105];
    int Next[25][105];
    void print(int i,int j)
    {
        if(j<=1)
            return ;
        print(Next[i][j], j-1);
        if(j>2)
            printf(" ");
        printf("%d",Next[i][j]);
    }
    int main()
    {
        while(scanf("%d%d", &n, &m)!=EOF)
        {
            for(int i=1;i<=n;i++)
                for(int j = 1;j<=m;j++)
                    scanf("%d", &a[i][j]);
            memset(Dp, 0x3f, sizeof(Dp));
            for(int i=1;i<=n;i++)
                Dp[i][m] = a[i][m];
            for(int i=m-1;i>0;i--)
            {
                for(int j=1;j<=n;j++)
                {
                    int s[3]={j-1,j,j+1};
                    if(j-1==0) s[0] = n;
                    if(j+1>n) s[2] = 1;
                    sort(s,s+3);
                    int t = s[0];
                    Dp[j][i] = Dp[t][i+1] + a[j][i];
                    Next[j][i] = t;
                    t = s[1] ;
                    if(Dp[j][i] > Dp[t][i+1] + a[j][i])
                    {
                        Dp[j][i] = Dp[t][i+1] + a[j][i];
                        Next[j][i] = t;    
                    }
                    t = s[2] ;
                    if(Dp[j][i] > Dp[t][i+1]+a[j][i])
                    {
                        Dp[j][i] = Dp[t][i+1] + a[j][i];
                        Next[j][i] = t;
                    }
                }
            }
            int ans =1;
            for(int i=2;i<=n;i++)
                if(Dp[ans][1] > Dp[i][1])
                    ans = i;
        //    print(ans,m);
            printf("%d",ans);
            int x =ans, y=1;
            while(y<m)
            {
                printf(" %d", Next[x][y]);
                x = Next[x][y];
                y++;
            }
            printf("
    %d
    ",Dp[ans][1]);
    
        }
        return 0;
    }
    /*
     * uva562
     * 给一列数,分成两堆,两堆的差最小;
     * 0-1背包处理出所有可能的和;
     * 然后从一半开始往下扫;
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int a[105];
    int Dp[50005];
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            int n;
            scanf("%d", &n);
            for(int i=0;i<n;i++)
                scanf("%d", &a[i]);
            int sum = 0;
            for(int i=0;i<n;i++)
                sum += a[i];
            memset(Dp, 0, sizeof(Dp));
            Dp[0] = 1;
            for(int j=0; j<n;j++)
                for(int i= sum; i>=a[j]; i--)
                    if(!Dp[i]) Dp[i] = Dp[i-a[j]];
            for(int i=sum/2;i>=0;i--)
                if(Dp[i])
                {
                    printf("%d
    ",sum-i-i);
                    break;
                }
        }
        return 0;
    }
    /*************************************************************************
     > File Name: uva348.cpp
     > Author: Baiyan
     > 题意:给一列矩阵的尺寸,问怎么样的计算顺序会使计算的次数最少
     >
     > Created Time: 2016年04月19日 星期二 22时52分37秒
     **********************************************************************/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    int a[15],b[15];
    int Dp[20][20];
    int vis[20][20];
    void print(int l,int r)
    {
        if(r-l>0)
        {
            printf("(");
            print(l,vis[l][r]);
            printf(" x ");
            print(vis[l][r]+1,r);
            printf(")");
        }
        else
            printf("A%d",l);
    }
    int main()
    {
        int n,k=1;
        while(scanf("%d", &n)!=EOF && n)
        {
            for(int i=1;i<=n;i++)
                scanf("%d%d", &a[i], &b[i]);
            memset(Dp, 0, sizeof(Dp));
            memset(vis,0, sizeof(vis));
            for(int p = 1;p<n;p++)
            {
                for(int i= 1;i+p<=n;i++)
                {
                    int j = i+p;
                    Dp[i][j] = INF;
                    for(int k = i; k<j; k++)
                    {
                        if(k==j)
                            Dp[k][j] = 0;
                        if(i==k)
                            Dp[i][k] = 0;
                        if(Dp[i][j] >= Dp[i][k]+Dp[k+1][j]+a[i]*b[j]*b[k])
                        {
                            vis[i][j] = k;
                            Dp[i][j] = Dp[i][k] + Dp[k+1][j] + a[i]*b[j]*b[k];
                        }
                    }
                }
            }
            printf("Case %d: ", k++);
            print(1,n);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Visual Studio 2008 每日提示(四)
    修改XP注册到用户名和公司组织名
    Visual Studio技巧之打造拥有自己标识的代码模板
    收集的学习资料
    多个记录更新(存储过程)
    '1,2,3,68,10'转换为'1,2,3,6,7,8,10'
    .NET程序员面试的题一部 (转)
    [.net]DataGrid中绑定DropDownList[转]
    使用DELETE与TRUNCATE删除表所有行的区别
    sysobjects 各列的含义
  • 原文地址:https://www.cnblogs.com/by-1075324834/p/5410607.html
Copyright © 2011-2022 走看看