HDU 3377 Plan

Problem Description
One day, Resty comes to an incredible world to seek Eve -- The origin of life. Lilith, the sister of Eve, comes with him. Although Resty wants to find Eve as soon as possible, Lilith likes to play games so much that you can't make her make any move if you don't play with her.

Now they comes to the magical world and Lilish ask Resty to play with her.

The game is following :
Now the world is divided into a m * n grids by Lilith, and Lilith gives each grid a score.
So we can use a matrix to describe it.
You should come from cell(0, 0) to cell(m-1, n-1) (Up-Left to Down-Right) and try to colloct as more score as possible.
According to Lilish's rule, you can't arrive at each cell more than once.

Resty knows that Lilish will be easy to find the max score, and he doesn't want to lose the game.
So he want to find the game plan to reach the max score.

Your task is to calculate the max score that Lilish will find, the map is so small so it shouldn't be difficult for you, right?
 

 

Input
The input consists of more than one testdata.
Process to the END OF DATA.
For each test data :
the first live give m and n. (1<=m<=8, 1<=n<=9)
following m lines, each contain n number to give you the m*n matrix.
each number in the matrix is between -2000 and 2000
 

 

Output
Output Format is "Case ID: ANS" one line for each data
Don't print any empty line to the output
 

 

Sample Input
2 2
1 2
3 1
3 3
0 -20 100
1 -20 -20
1 1 1
 

 

Sample Output
Case 1: 5
Case 2: 61
 
插头dp
左上角走到右下角,不得重复经过格子,也可以不经过,求最大分数。
两种方法,第一是上下加两行,加两列,加障碍,使题目变成简单的回路,而不是单路。
第二在起点终点都加一个单插头处理,其他地方也应相应微调,不过我好像调得不好,一直WA……233,不过本机测了数百组数据都是对哒,所以不管了……
/*第一种方法*/
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mn=977147;
int i;
struct na{
    int x,z;
    na(int xx,int zz):x(xx),z(zz){}
};
int n,m,x,y,z,a[21],k,en,u=0,p1,p2;
bool map[21][21];
int f[2][mn+1],ans;
int v[2][mn+1];
int re[21][21];
queue <na> q;
inline int gx(int x,int q1,int q2){k=0;for (register int i=m+1;i;i--) k=k*3+(i==x?q1:(i==x+1?q2:a[i]));return k;}
inline void up(int x,int z,int lj,bool la){
    if (la) lj+=re[x/m+1][x%m+1];
    x++;
    k=x%2;
    if (v[k][z]!=x) v[k][z]=x,f[k][z]=-1e9,q.push(na(x,z));
    f[k][z]=max(f[k][z],lj);
}
int main(){
    //freopen("a.in","r",stdin);
    register int i,j;
    while(scanf("%d%d",&n,&m)!=EOF){
        u++;
        printf("Case %d: ",u);
        ans=-1e9;
        memset(map,0,sizeof(map));memset(v,0,sizeof(v));memset(re,0,sizeof(re));memset(f,0,sizeof(f));
        for (i=1;i<=m;i++)
        for (j=1;j<=n;j++)
        map[i][j+2]=1;
        for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
        scanf("%d",&re[i+2][j]);
        n+=4;
        m+=2;
        en=n*m-1;
        for (i=1;i<=m;i++) map[i][1]=map[i][n]=1;
        for (i=1;i<=n;i++) map[m][i]=1;
        map[1][2]=1;map[m-2][n-1]=1;
        if (n==1&&m==1){
            printf("%d\n",re[1][1]);
            continue;
        }
        f[0][0]=0;v[0][0]=1;
        q.push(na(0,0));
        while(!q.empty()){
            na no=q.front();q.pop();
            int an=f[no.x%2][no.z];
            if(no.x%m==0) no.z*=3;
            x=no.x%m+1;y=no.x/m+1;
            for (i=1;i<=m+1;i++) a[i]=0;
            for (i=1,j=no.z;j;i++,j/=3) a[i]=j%3;
            if (!map[x][y])up(no.x,gx(x,0,0),an,0);else
            if (a[x]==1&&a[x+1]==2){
                if (no.x==en) ans=max(ans,an);
            }else if (a[x]==2&&a[x+1]==1) up(no.x,gx(x,0,0),an,1);else
                if (a[x]==0&&a[x+1]==0){
                if (no.x!=en&&no.x!=1) up(no.x,gx(x,0,0),an,0);
                if (map[x][y+1]&&map[x+1][y]) up(no.x,gx(x,1,2),an,1);
            }else if (a[x]==0){
                if (map[x+1][y]) up(no.x,gx(x,0,a[x+1]),an,1);
                if (map[x][y+1]) up(no.x,gx(x,a[x+1],0),an,1);
            }else if (a[x+1]==0){
                if (map[x+1][y]) up(no.x,gx(x,0,a[x]),an,1);
                if (map[x][y+1]) up(no.x,gx(x,a[x],0),an,1);
            }else if (a[x]==a[x+1]){
                p1=p2=0;
                if (a[x]==1)
                for (j=0,i=x+2;i<=m;i++){
                    if (a[i]==1) j--;
                    if (a[i]==2) j++;
                    if (j>0&&!p1) p1=i,j--;
                    if (j>0&&p1){p2=i;break;}
                }else
                for (j=0,i=x-1;i;i--){
                    if (a[i]==1) j++;
                    if (a[i]==2) j--;
                    if (j>0&&!p2) p2=i,j--;
                    if (j>0&&p2){p1=i;break;}
                }
                a[p1]=1;a[p2]=2;up(no.x,gx(x,0,0),an,1);
            }
        }
        printf("%d\n",ans);
    }
}
/*第二种方法*/
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int i;
struct na{
    int x,z;
    na(int xx,int zz):x(xx),z(zz){}
};
int n,m,x,y,z,a[21],k,en,u=0,p1,p2;
bool map[21][21];
int f[2][1277148],ans;
int v[2][1277148];
int re[21][21];
queue <na> q;
inline int gx(int x,int q1,int q2){k=0;for (register int i=m+1;i;i--) k=k*3+(i==x?q1:(i==x+1?q2:a[i]));return k;}
inline void up(int x,int z,int lj,bool la){
    if (la) lj+=re[x/m+1][x%m+1];
    x++;
    k=x%2;
    if (v[k][z]!=x) v[k][z]=x,f[k][z]=lj,q.push(na(x,z));
    if (lj>f[k][z]) f[k][z]=lj;
}
int main(){
    register int i,j;
    while(scanf("%d%d",&n,&m)!=EOF){
        u++;
        ans=0;
        memset(map,0,sizeof(map));memset(v,0,sizeof(v));memset(f,0,sizeof(f));
        en=n*m-1;
        for (i=1;i<=m;i++)
        for (j=1;j<=n;j++)
        map[i][j]=1;
        for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
        scanf("%d",&re[i][j]);
        if (n==1&&m==1){
            printf("Case %d: %d\n",u,re[1][1]);
            continue;
        }
        f[0][1]=0;
        v[0][0]=1;
        q.push(na(0,1));
        while(!q.empty()){
            na no=q.front();q.pop();
            int an=f[no.x%2][no.z];
            if (no.x%m==0) no.z*=3;
            x=no.x%m+1;y=no.x/m+1;
            for (i=1;i<=m+1;i++) a[i]=0;
            for (i=1,j=no.z;j;i++,j/=3) a[i]=j%3;
            if (no.x==en){
                k=0;
                for (i=1;i<=m+1;i++) k+=a[i]!=0;
                if (k==1&&(a[m]==1||a[m+1]==1)&&an+re[n][m]>ans) ans=an+re[n][m];
                continue;
            }
            if (a[x]==2&&a[x+1]==1){
                up(no.x,gx(x,0,0),an,1);
            }else if (a[x]==0&&a[x+1]==0){
                up(no.x,gx(x,0,0),an,0);
                if (map[x][y+1]&&map[x+1][y])
                up(no.x,gx(x,1,2),an,1);
            }else if (a[x]==0){
                if (map[x+1][y]) up(no.x,gx(x,0,a[x+1]),an,1);
                if (map[x][y+1]) up(no.x,gx(x,a[x+1],0),an,1);
            }else if (a[x+1]==0){
                if (map[x+1][y]) up(no.x,gx(x,0,a[x]),an,1);
                if (map[x][y+1]) up(no.x,gx(x,a[x],0),an,1);
            }else if (a[x]==1&&a[x+1]==1){
                p1=p2=0;
                for (j=0,i=x+2;i<=m+1;i++){
                    if (a[i]==1) j--;
                    if (a[i]==2) j++;
                    if (j>0&&!p1) p1=i,j--;
                    if (j>0&&p1){p2=i;break;}
                }
                a[p1]=1;a[p2]=2;
                up(no.x,gx(x,0,0),an,1);
            }else if (a[x]==2&&a[x+1]==2){
                p1=p2=0;
                for (j=0,i=x-1;i;i--){
                    if (a[i]==1) j++;
                    if (a[i]==2) j--;
                        if (j>0&&!p2) p2=i,j--;
                    if (j>0&&p2){p1=i;break;}
                }
                a[p1]=1;a[p2]=2;up(no.x,gx(x,0,0),an,1);
            }
        }
        printf("Case %d: %d\n",u,ans);
    }
}

 

转载于:https://www.cnblogs.com/Enceladus/p/5137176.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值