zoukankan      html  css  js  c++  java
  • Mark一下, dp状态转移方程写对,可是写代码都错,poj 1651 poj 1179

    dp题:
    1、写状态转移方程;

    2、考虑初始化边界,有意义的赋定值。还没计算的赋边界值;

    3、怎么写代码自底向上计算最优值

    今天做了几个基础dp,所有是dp方程写对可是初始化以及计算写错

    先是poj 1651 事实上就是个赤裸裸的矩阵连乘。dp方程非常easy写出

                          dp[i][j]=min(dp[i][k]+dp[k+1][j]+r[i]*c[k]*c[j],dp[i][j]);

    先贴两个个二逼的代码,mark下自己多么的二逼:

    二逼一:在计算的时候使用了还没有算出来的值,模拟下就知道第一重循环里算dp[0][2]=dp[0][0]+dp[1][2];

    !!!!!dp[1][2]这时候根本没有计算出来还,Tmd我就用了这个值!!

    。!!!!

    !。!

    。!

    !。!

    。。!。。!

    二逼啊!

    !!!

    !。。!


    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    
    using namespace std;
    
    
    const int SIZE = 100+10;
    const int INF = 10000000;
    int dp[SIZE][SIZE];
    int r[SIZE],c[SIZE];
    
    
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
    
    
            for(int i=0;i<n-1;i++)
            {
                scanf("%d",&r[i]);
                if(i>0)c[i-1]=r[i];
            }
            scanf("%d",&c[n-2]);
            n--;
            int ans=0;
            for(int i=0;i<n;i++)dp[i][i]=0;
    
    
            for(int i=0;i<=n;i++)
                for(int j=i;j<n;j++)
                {
    
    
                    for(int k=i;k<j;k++)
                        dp[i][j]=min(dp[i][k]+dp[k+1][j]+r[i]*c[k]*c[j],dp[i][j]);
                }
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                    printf("%d ",dp[i][j]);
                putchar('
    ');
            }
    
    
    
    
            printf("%d
    ",dp[0][n-1]);
    
    
        }
        return 0;
    }
    

    二逼二:来回换思路的时候各种思路弄混。看凝视

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int SIZE = 100+10;
    const int INF = 10000000;
    int dp[SIZE][SIZE];
    int r[SIZE],c[SIZE];
    
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
    
            for(int i=0;i<n-1;i++)
            {
                scanf("%d",&r[i]);
                if(i>0)c[i-1]=r[i];
            }
            scanf("%d",&c[n-2]);
            n--;
            int ans=0;
            for(int i=0;i<n;i++)dp[i][i]=0;
            int j;
            for(int l=2;l<=n;l++)
                for(int i=0;i<l;i++)//此处i<l及其傻逼,请勿模仿
                {
                    j=i+l-1;
                    dp[i][j]=INF;
                    for(int k=i;k<j;k++)
                        dp[i][j]=min(dp[i][k]+dp[k+1][j]+r[i]*c[k]*c[j],dp[i][j]);
                }
            /*for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                    printf("%d ",dp[i][j]);
                putchar('
    ');
            }*/
    
    
            printf("%d
    ",dp[0][n-1]);
    
        }
        return 0;
    }
    

    正确代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    const int SIZE = 100+10;
    const int INF = 200000000;
    ll dp[SIZE][SIZE];
    int r[SIZE],c[SIZE];
    
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
    
            for(int i=0;i<n-1;i++)
            {
                scanf("%d",&r[i]);
                if(i>0)c[i-1]=r[i];
            }
            scanf("%d",&c[n-2]);
            n--;
            int ans=0;
            for(int i=0;i<=n;i++)dp[i][i]=0;
            int j;
            for(int l=2;l<=n;l++)
                for(int i=0;i<n-l+1;i++)
                {
                    j=i+l-1;
                    dp[i][j]=INF;
                    for(int k=i;k<j;k++)
                        dp[i][j]=min(dp[i][k]+dp[k+1][j]+r[i]*c[k]*c[j],dp[i][j]);
                }
            printf("%lld
    ",dp[0][n-1]);
    
        }
        return 0;
    }
    

    在做这个poj 1651之前  先做的poj 1179,然后过了poj 1651之后改了poj1179原来的循环次序,事实上就是类比这个poj1651,第一重循环弄成长度就可以

    注意 负数乘以负数是正数 考虑最大最小值得时候一定注意

    只是又一次检查下发现代码在初始化的时候冗余,精简了下。

    贴代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    
    const int SIZE =55;
    const int INF =  (-2147483647 ) ;
    
    ll dp[SIZE][SIZE],dpmin[SIZE][SIZE];
    int pos[SIZE];
    bool op[SIZE];
    
    int main()
    {
        //freopen("poj1179.txt","r",stdin);
        int n;
        ll tmp1,tmp2;
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=0;i<n;i++)dp[i][0]=dpmin[i][0]=0;
            for(int i=0;i<n;i++)
            {
                scanf(" %c %lld",&op[i],&dp[i][1]);
                dpmin[i][1]=dp[i][1];
            }
            for(int j=1;j<=n;j++)
                for(int i=0;i<n;i++)
                {
                    if(j>1)dp[i][j]=INF,dpmin[i][j]=-INF;
                    for(int k=1;k<j;k++)
                    {
                        if(op[(i+k)%n ] == 't')
                        {
                            dp[i%n][j]=max(dp[i%n][k]+dp[(i+k)%n ][j-k],dp[i%n][j]);
                            dpmin[i%n][j]=min(dpmin[i%n][k]+dpmin[(i+k)%n ][j-k], dpmin[i%n][j]);
                        }
    
                        else
                        {
                            tmp1=max(dp[i%n][k]*dp[(i+k)%n ][j-k],dpmin[i%n][k]*dpmin[(i+k)%n ][j-k]);
                            tmp2=max(dp[i%n][k]*dpmin[(i+k)%n ][j-k], dpmin[i%n][k]*dp[(i+k)%n ][j-k]);
                            tmp1=max(tmp1,tmp2);
                            dp[i%n][j]=max(tmp1,dp[i%n][j]);
                            tmp2=min(dp[i%n][k]*dp[(i+k)%n ][j-k],dpmin[i%n][k]*dpmin[(i+k)%n ][j-k]);
                            tmp1=min(dp[i%n][k]*dpmin[(i+k)%n ][j-k], dpmin[i%n][k]*dp[(i+k)%n ][j-k]);
                            tmp2=min(tmp1,tmp2);
                            dpmin[i%n][j]=min(dpmin[i%n][j],tmp2);
                        }
    
                    }
                }
            int cnt=0;
            ll ans=INF;
            for(int i=0;i<n;i++)//開始的时候,这里i<=n。于是初始化的时候必须优dp[n][...]=INF,才干AC,奇怪的是计算过程中第一个下标我都%n了,最后才看到这里的问题
            {
                ans=max(ans,dp[i][n]);
            }
            for(int i=0;i<n;i++)
                if(ans == dp[i][n])
                    pos[cnt++]=i+1;
    
            printf("%lld
    ",ans);
            for(int i=0;i<cnt;i++)
                if(i == cnt-1)printf("%d
    ",pos[i]);
                else printf("%d ",pos[i]);
        }
    
        return 0;
    }
    


  • 相关阅读:
    下四国的排长和下四国的小兵 (转载)
    RSS Bandit 不能显示中文界面的解决方法
    Google桌面搜索(GDS)插件的开发工具
    编写VxWorks的Hello World程序
    Visual Studio 2005 Express October 2004 CTP完整版本的下载
    压缩.NET可执行文件的工具
    支持x64的开发工具
    Visual Studio.NET 2002的Service Pack 1发布了
    Windows 嵌入式开发的一些Blog
    利用BITSADMIN获得下载地址
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7238690.html
Copyright © 2011-2022 走看看