hdu2167 轮廓线动态规划

来源:互联网 发布:淘宝网电视机 编辑:程序博客网 时间:2024/05/19 20:57

输入比较难处理,周围8格数字不可取。因为必须要记录当前格左上角的数字有没有取得情况,所以所以要在一般的轮廓线上加一位,并且换行时要更新一下状态。如下图:
图片
状态记录及转移
在取11格的数字时,我们需要判断10,6,7,8格是否有取数字。在更新11格的状态的同时,丢弃掉第6格的状态值。在遇到换行时,第8格的状态可以直接丢弃,但是我们要虚拟出一个新的格,方便下一次的状态转移。这题要理解多加的状态,以及换行时的状态变化。此时的状态记录已经类似于下面说的轮廓线了。代码如下:

#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<string>#include<set>#include<map>#include<queue>#include<stack>#include<cstring>using namespace std;#define LL long longLL dp[2][1<<16];int main(){    LL dat[20][20];    int n = 1;    while(scanf("%lld",&dat[0][0])!=EOF)    {        n = 1;        while(1)        {            char ch;            scanf("%c",&ch);            if(ch==' ')n++;            else break;            scanf("%lld",&dat[0][n-1]);        }        for(int i = 1;i<n;i++)        {            for(int j = 0;j<n;j++)            {                scanf("%lld",&dat[i][j]);            }        }        memset(dp,-1,sizeof(dp));        dp[0][0] = 0;        int cur = 0;        for(int i = 0;i<n;i++)        {            for(int j = 0;j<n;j++)            {                for(int k = 0;k<(1<<n+1);k++)                {                    if(dp[cur][k]<0)continue;                    // 不选                    dp[1-cur][(k<<1) & (1<<n+1)-1] = max(dp[1-cur][(k<<1) & (1<<n+1)-1],dp[cur][k]);                    // 选                    if(j==0) // 只需要第二和第三位                    {                        if((k & (1<<n-1))==0 && (k & (1<<n-2))==0)                        {                            //cout << "k" << endl;                            dp[1-cur][((k<<1)|1) & (1<<n+1)-1] = max(dp[1-cur][((k<<1)|1) & (1<<n+1)-1],dp[cur][k]+dat[i][j]);                        }                    }                    else if(j==n-1) // 只需第一 第二 最后位                    {                        if((k & (1<<n-1)) == 0 && (k & (1<<n)) == 0 && (k&1)==0)                        {                            dp[1-cur][((k<<1)|1) & (1<<n+1)-1] = max(dp[1-cur][((k<<1)|1) & (1<<n+1)-1],dp[cur][k]+dat[i][j]);                        }                    }                    else                    {                        if((k & (1<<n)) == 0 && (k & (1<<n-1)) == 0 && (k & (1<<n-2)) == 0 && (k&1)==0)                        {                            dp[1-cur][((k<<1)|1) & (1<<n+1)-1] = max(dp[1-cur][((k<<1)|1) & (1<<n+1)-1],dp[cur][k]+dat[i][j]);                        }                    }                }                memset(dp[cur],-1,sizeof(dp[cur]));                cur = 1^cur;                //cout << dp[cur][1] << endl;            }        }        LL ans = 0;        for(int i = 0;i<(1<<n+1);i++)        {            ans = max(dp[cur][i],ans);            //cout << ans << endl;        }        printf("%lld\n",ans);    }    return 0;}
原创粉丝点击