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
- poj 3133 Manhattan Wiring
- POJ 3133 Manhattan Wiring
- POJ 3133 Manhattan Wiring
- POJ 3133 Manhattan Wiring
- poj 3133 Manhattan Wiring
- POJ 3133 Manhattan Wiring 笔记
- poj 3133 Manhattan Wiring 插头dp
- poj 3133 Manhattan Wiring 插头dp
- poj 3133 Manhattan Wiring (插头dp)
- poj 3133 -- Manhattan Wiring 插头dp
- POJ 3133 Manhattan Wiring 解题报告(插头DP)
- [省选前题目整理][POJ 3133]Manhattan Wiring(插头DP)
- poj 3133&&LA 3620 Manhattan Wiring 插头dp
- POJ 3133 Manhattan Wiring(限制匹配的插头DP)
- POJ 3113 Manhattan Wiring(插头DP)
- Manhattan Wiring poj3133
- uva1214 - Manhattan Wiring 插头DP
- [POJ3133]Manhattan Wiring 插头dp
- nginx与ios实现https双向认证
- 不同数据库查询
- cocos2d-android学习二 ------cocos2d安装
- 每天进步一点
- com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
- POJ 3133 Manhattan Wiring
- Apple 企业开发者账号&邓白氏码申请记录
- 第十二周 项目一 长颈鹿对动物类的继承(2)
- 互联网实习面试经验
- 在Android使用正则表达式
- 关于Python发帖机
- 开源的Android视频播放器
- 后置增强的实现
- Android源码make常见错误