hdu3377

题解:

简单的插头dp

加上一个代价即可

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=15,HASH=10007,STATE=1000100,M=1e9+7;
typedef long long ll;
int n,m,ch[N],code[N],mp[N][N],mp2[N][N];
struct HASHMAP
{
    int head[HASH],next[STATE],size;
    ll state[STATE],f[STATE];
    void init()
     {
        size=0;
        memset(head,-1,sizeof(head));
     }
    void push(ll st,ll ans)
     {
        int h=st%HASH;
        for (int i=head[h];i!=-1;i=next[i])
         if (state[i]==st)
          {
            f[i]=max(ans,f[i]);
            return;
          }
        state[size]=st;
        f[size]=ans;
        next[size]=head[h];
        head[h]=size++;
     }
}hm[2];
void decode(ll st) 
{
    for (int i=m;i>=0;i--)
     {
        code[i]=st&7;
        st>>=3;
     }
}
ll encode()
{
    int cnt=1;
    ll st=0;
    memset(ch,-1,sizeof(ch));
    ch[0]=0;ch[7]=7;
    for (int i=0;i<=m;i++)
     {
        if (ch[code[i]]==-1)ch[code[i]]=cnt++;
        code[i]=ch[code[i]];
        st<<=3;
        st|=code[i];
     }
    return st;
}
void shift()
{
    for (int i=m;i;i--)code[i]=code[i-1];
    code[0]=0;
}
void dp(int r,int c,int cur)
{
    for (int k=0;k<hm[cur].size;k++)
     {
        decode(hm[cur].state[k]);
        int up=code[c],left=code[c-1];
        if ((r==1&&c==1)||(r==n&&c==m))
         {
            if (!up&&!left)
             {
                if (c<m)
                 {
                    code[c]=7;
                    code[c-1]=0;
                    hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
                 }
                if (r<n)
                 {
                    code[c]=0;
                    code[c-1]=7;
                    if (m==c)shift();
                    hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
                 }
             }
            if (up||left)
             {
                code[c]=code[c-1]=0;
                if (m==c)shift();
                hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
             }
            continue;
         }
        if (up&&left)
         {
            if (up!=left)
             {
                int t=max(up,left);
                code[c]=code[c-1]=0;
                for (int i=0;i<=m;i++) 
                 if (code[i]==left||code[i]==up)code[i] = t;
                if (m==c) shift();
                hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
             }
         }
        else if (up||left)
         {
            if (c<m)
             {
                code[c-1]=0;
                code[c]=up|left;
                if (m==c)shift();
                hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
             }
            if (r<n)
             {
                code[c-1]=up|left;
                code[c]=0;
                if (m==c) shift();
                hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]); 
             }
         }
        else
         {
            if (c<m&&r<n)
             {
                code[c-1]=code[c]=6;
                hm[cur^1].push(encode(),hm[cur].f[k]+mp[r][c]);
             }
            code[c]=code[c-1]=0;
            if (c==m) shift();
            hm[cur^1].push(encode(),hm[cur].f[k]);
         }
     }
}
int main()
{
    int cas=0;
    while (~scanf("%d%d",&n,&m))
     {
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)scanf("%d", &mp[i][j]);
        if (n==1&&m==1)
         {
            printf("Case %d: %d
",++cas,mp[1][1]);
            continue;
         }
        if (n<m)
         {
            for (int i=1;i<=m;i++)
             for (int j=1;j<=n;j++)mp2[i][j]=mp[j][i];
            for (int i=1;i<=m;i++)
             for (int j=1;j<=n;j++)mp[i][j]=mp2[i][j];
            swap(n,m);
         }
        int cur=0;
        hm[cur].init();
        hm[cur].push(0,0);
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
          {
            hm[cur^1].init();
            dp(i,j,cur);
            cur^=1;
          }
        ll ans=-1e18;
        for (int i=0;i<hm[cur].size;i++)ans=max(ans,hm[cur].f[i]);
        printf("Case %d: %lld
",++cas,ans);
     }   
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8671365.html