POJ 3133 Manhattan Wiring

来源:互联网 发布:杀人漫画剧情知乎 编辑:程序博客网 时间:2024/05/21 12:41

将格子中的两个2和两个3连起来,求经过总的格子数的总和减2.

Hint:两条路径不能交叉,有障碍格子。非障碍格子只能经过一次。

SOL:

插头记录三种状态: 0----没有插头

2----数字2

3----数字3


用四进制优于三进制。


#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;const int MAXD=15;const int HASH=10007;const int STATE=1000010;int N,M;int maze[MAXD][MAXD];//0表示障碍,1是非障碍,2和3int code[MAXD];//0表示没有插头,2表示和插头2相连,3表示和插头3相连struct HASHMAP{    int head[HASH],next[STATE],size;    int state[STATE];    int dp[STATE];    void init()    {        size=0;        memset(head,-1,sizeof(head));    }    void push(int st,int ans)    {        int i,h=st%HASH;        for(i=head[h];i!=-1;i=next[i])          if(state[i]==st)          {              if(dp[i]>ans)dp[i]=ans;              return;          }        state[size]=st;        dp[size]=ans;        next[size]=head[h];        head[h]=size++;    }}hm[2];void decode(int *code,int m,int st)//四进制{    int i;    for(int i=m;i>=0;i--)    {        code[i]=(st&3);        st>>=2;    }}int encode(int *code,int m){    int i;    int st=0;    for(int i=0;i<=m;i++)    {        st<<=2;        st|=code[i];    }    return st;}void shift(int *code,int m)//换行{    for(int i=m;i>0;i--)code[i]=code[i-1];    code[0]=0;}void dpblank(int i,int j,int cur){    int k,left,up;    for(k=0;k<hm[cur].size;k++)    {        decode(code,M,hm[cur].state[k]);        left=code[j-1];        up=code[j];        if(left&&up)        {            if(left==up)//只能是相同的插头            {                code[j-1]=code[j]=0;                if(j==M)shift(code,M);                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }        }        else if((left&&(!up))||((!left)&&up))//只有一个插头        {            int t;            if(left)t=left;            else t=up;//这里少写个else ,查了好久的错误            if(maze[i][j+1]==1||maze[i][j+1]==t)//插头从右边出来            {                code[j-1]=0;                code[j]=t;                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }            if(maze[i+1][j]==1||maze[i+1][j]==t)//插头从下边出来            {                code[j]=0;                code[j-1]=t;                if(j==M)shift(code,M);                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }        }        else if(left==0&&up==0)//没有插头        {            code[j-1]=code[j]=0;//不加插头            if(j==M)shift(code,M);            hm[cur^1].push(encode(code,M),hm[cur].dp[k]);            if(maze[i][j+1]&&maze[i+1][j])            {                if(maze[i][j+1]==1&&maze[i+1][j]==1)                {                    decode(code,M,hm[cur].state[k]);                    code[j-1]=code[j]=2;//加2号插头                    hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);                    //decode(code,M,hm[cur].state[k]);                    code[j-1]=code[j]=3;//加3号插头                    hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);                }                else if((maze[i][j+1]==2&&maze[i+1][j]==1)||(maze[i+1][j]==2&&maze[i][j+1]==1)||(maze[i][j+1]==2&&maze[i+1][j]==2))                {                    decode(code,M,hm[cur].state[k]);                    code[j-1]=code[j]=2;                    hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);                }                else if((maze[i][j+1]==3&&maze[i+1][j]==1)||(maze[i+1][j]==3&&maze[i][j+1]==1)||(maze[i][j+1]==3&&maze[i+1][j]==3))                {                    decode(code,M,hm[cur].state[k]);                    code[j-1]=code[j]=3;                    hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);                }            }        }    }}void dpblock(int i,int j,int cur){    int k;    for(k=0;k<hm[cur].size;k++)    {        decode(code,M,hm[cur].state[k]);        if(code[j-1]!=0||code[j]!=0)continue;        code[j-1]=code[j]=0;//不加插头        if(j==M)shift(code,M);        hm[cur^1].push(encode(code,M),hm[cur].dp[k]);    }}void dp_2(int i,int j,int cur){    int left,up,k;    for(k=0;k<hm[cur].size;k++)    {        decode(code,M,hm[cur].state[k]);        left=code[j-1];        up=code[j];        if((left==2&&up==0)||(left==0&&up==2))        {            code[j-1]=code[j]=0;            if(j==M)shift(code,M);            hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);        }        else if(left==0&&up==0)        {            if(maze[i][j+1]==1||maze[i][j+1]==2)            {                code[j-1]=0;                code[j]=2;                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }            if(maze[i+1][j]==1||maze[i+1][j]==2)            {                code[j-1]=2;                code[j]=0;                if(j==M)shift(code,M);                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }        }    }}void dp_3(int i,int j,int cur){    int left,up,k;    for(k=0;k<hm[cur].size;k++)    {        decode(code,M,hm[cur].state[k]);        left=code[j-1];        up=code[j];        if((left==3&&up==0)||(left==0&&up==3))        {            code[j-1]=code[j]=0;            if(j==M)shift(code,M);            hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);        }        else if(left==0&&up==0)        {            if(maze[i][j+1]==1||maze[i][j+1]==3)            {                code[j-1]=0;                code[j]=3;                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }            if(maze[i+1][j]==1||maze[i+1][j]==3)            {                code[j-1]=3;                code[j]=0;                if(j==M)shift(code,M);                hm[cur^1].push(encode(code,M),hm[cur].dp[k]+1);            }        }    }}void init(){    memset(maze,0,sizeof(maze));    for(int i=1;i<=N;i++)      for(int j=1;j<=M;j++)      {          scanf("%d",&maze[i][j]);          if(maze[i][j]==0)maze[i][j]=1;          else if(maze[i][j]==1)maze[i][j]=0;          //两种表达方式           //if(maze[i][j]==1||maze[i][j]==0)maze[i][j]^=1;//0变1,1变0      }}void solve(){    int i,j,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();          if(maze[i][j]==0)dpblock(i,j,cur);          else if(maze[i][j]==1)dpblank(i,j,cur);          else if(maze[i][j]==2)dp_2(i,j,cur);          else if(maze[i][j]==3)dp_3(i,j,cur);          cur^=1;      }    int ans=0;    for(int i=0;i<hm[cur].size;i++)      ans+=hm[cur].dp[i];    if(ans>0)ans-=2;    printf("%d\n",ans);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(scanf("%d%d",&N,&M))    {        if(N==0&&M==0)break;        init();        solve();    }    return 0;}


0 0
原创粉丝点击