• uva 10003 Cutting Sticks


    DP(类似于矩阵链乘法)

    我们以sample来说明问题

    长度100,切的地方为25,50,75.

    那么无论怎么切最后都是剩下四段 [0,25] , [25,50] , [50,75] , [75,100]

    把它们连续的两两合并的话就能得到上一层的状态,好像[0,25]和[25,50]合并,就得到[0,50],也就是说从[0,50]变到[0,25] , [25,50],花费是多少呢,就是50

    所以说到这里,也差不多了,状态转移方程为 dp[i][j]=min{ dp[i][k]+dp[k][j]+(y-x)}  (k是i和j之间的一个数)

    这样子的话,我们的目标状态就是dp[0][len],即原来的整一条的费用。

    这个时候无论是用递推还是用记忆化搜索去做都非常形象,非常好懂。

    另外dp[i][j]里面的ij表示的确切的长度,而数据中木棒的长度上限为1000,所以dp数组大小要为dp[1000][1000]。当然可以优化一下空间,同时也提高了一些时间

    dp[i][j]的i和j表示数据中的第i刀和第j刀,这样其实也起到了表示长度的作用,因为数据说明中说了切的地方是严格递增的序列。所以dp数组的大小只需要开到dp[50][50] , 因为最多切50刀

    记忆化搜索(0.500s)

    #include <cstdio>
    #include <cstring>
    #define M 60
    #define N 1010
    #define INF 0x3f3f3f3f
    int a[M],dp[N][N];
    int n,m;
    
    int min(int i ,int j)
    { return i<j?i:j; }
    
    void dfs(int x , int y)
    {
        if(dp[x][y]!=INF)
            return ;
        for(int i=1; a[i]<y; i++)
            if(a[i]>x)
            {
                dfs(x,a[i]);
                dfs(a[i],y);
                dp[x][y]=min(dp[x][y] , dp[x][a[i]]+dp[a[i]][y]+(y-x) );
            }
        return ;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            scanf("%d",&m);
            a[0]=0;
            for(int i=1; i<=m; i++)
                scanf("%d",&a[i]);
            a[m+1]=n;
            //memset(dp,0x3f,sizeof(dp));
            for(int i=0; i<=m; i++)
                dp[a[i]][a[i+1]]=0;
            for(int l=2; l<=m+1; l++)
                for(int i=0; i<=m-l+1; i++)
                    dp[a[i]][a[i+l]]=INF;
    
            dfs(0,n);
            printf("The minimum cutting is %d.\n",dp[0][n]);
        }
        return 0;
    }

    递推(0.108s)

    #include <cstdio>
    #include <cstring>
    #define M 60
    #define N 1010
    #define INF 0x3f3f3f3f
    int a[M],dp[N][N];
    int n,m;
    
    int min(int i ,int j)
    { return i<j?i:j; }
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            scanf("%d",&m);
            a[0]=0; a[m+1]=n;
            for(int i=1; i<=m; i++)
                scanf("%d",&a[i]);
            //memset(dp,0x3f,sizeof(dp));  
            //并不是所有状态都要清INF,否则会TLE
            for(int i=0; i<=m; i++)
                dp[a[i]][a[i+1]]=0;
    
            for(int l=2; l<=m+1; l++)  //把多少块合并
                for(int i=0; i<=m-l+1; i++) //标号
                {
                    int j=i+l , x=a[i] , y=a[j];
                    dp[x][y]=INF;
                    for(int k=i+1; k<j; k++)
                        dp[x][y]=min(dp[x][y] , dp[x][a[k]]+dp[a[k]][y]+y-x);
                }
            printf("The minimum cutting is %d.\n",dp[0][n]);
        }
        return 0;
    }

    递推优化加速(0.072s)(只是修改了一些微小的地方,思想和上面的递推是完全一样的)

    #include <cstdio>
    #include <cstring>
    #define M 60
    #define N 1010
    #define INF 0x3f3f3f3f
    int a[M],dp[M][M];
    int n,m;
    
    int min(int i ,int j)
    { return i<j?i:j; }
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            scanf("%d",&m);
            a[0]=0; a[m+1]=n;
            for(int i=1; i<=m; i++)
                scanf("%d",&a[i]);
            //memset(dp,0x3f,sizeof(dp));  
            //并不是所有状态都要清INF,否则会TLE
            for(int i=0; i<=m; i++)
                dp[i][i+1]=0;
    
            for(int l=2; l<=m+1; l++)  //把多少块合并
                for(int i=0; i<=m-l+1; i++) //标号
                {
                    int j=i+l,Min=INF;
                    for(int k=i+1; k<j; k++)
                        Min=min(Min , dp[i][k]+dp[k][j]);
                    dp[i][j]=Min+a[j]-a[i];
                }
            printf("The minimum cutting is %d.\n",dp[0][m+1]);
        }
        return 0;
    }
  • 相关阅读:
    Qt Installer Framework翻译(3-4)
    Qt Installer Framework翻译(3-3)
    Qt Installer Framework翻译(3-2)
    Qt Installer Framework翻译(3-1)
    Qt Installer Framework翻译(3-0)
    Qt Installer Framework翻译(0)
    Qt Installer Framework翻译(2)
    Qt Installer Framework翻译(1)
    野生前端的数据结构基础练习(8)——图
    野生前端的数据结构基础练习(7)——二叉树
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2833906.html
Copyright © 2020-2023  润新知