zoj 3814 Sawtooth Puzzle
2014-11-14 08:23
375 查看
题意:9张正方形卡片摆成3*3,每张卡片有图案,求从当前状态旋转到目标状态的最短步。卡片的某些边类似齿轮,如果相邻的边都是齿轮边,它们就会同时旋转。
思路:搜索。这个题比较复杂,涉及到好多问题,比如状态的编码解码,图像相同的校验,旋转的模拟等等。首先编码问题用9位4进制数表示,我因为编码解码写错WA了好多发。。图像相同的校验暴力解决,注意可能出现对称的情况,即多个相同态。旋转的模拟用dfs(bfs超时),搜索哪些卡片会被带动,根据与原卡片的曼哈顿距离的奇偶性确定旋转方向。
程序的主体当然是BFS,因为需要求最短步,里面套一下上述功能就可以了。
思路:搜索。这个题比较复杂,涉及到好多问题,比如状态的编码解码,图像相同的校验,旋转的模拟等等。首先编码问题用9位4进制数表示,我因为编码解码写错WA了好多发。。图像相同的校验暴力解决,注意可能出现对称的情况,即多个相同态。旋转的模拟用dfs(bfs超时),搜索哪些卡片会被带动,根据与原卡片的曼哈顿距离的奇偶性确定旋转方向。
程序的主体当然是BFS,因为需要求最短步,里面套一下上述功能就可以了。
#include<iostream> #include<cmath> #include<queue> #include<vector> #include<algorithm> #include<string.h> #include<cstdio> using namespace std; #define INF 100000000 char G[10][10][10]; char G2[10][10][10]; bool st[10][4]; int match[10][4]; //哪些状态可看作终态 int dis[266666]; //存每个状态与初态距离 //判断是否为终态 bool judge(int s){ for(int t=8;t>=0;t--){ int cur=s%4; s/=4; if(!match[t][cur])return 0; } return 1; } bool r[9]; int s[9]; bool dfs(int cur){ if(cur>2){//上 if(!r[cur-3])if(st[cur][(5-s[cur])%4]&&st[cur-3][(3-s[cur-3])%4]){ r[cur-3]=1; dfs(cur-3); } } if(cur<6){//下 if(!r[cur+3])if(st[cur][(3-s[cur])%4]&&st[cur+3][(5-s[cur+3])%4]){ r[cur+3]=1; dfs(cur+3); } } if(cur%3!=0){//左 if(!r[cur-1])if(st[cur][(4-s[cur])%4]&&st[cur-1][(6-s[cur-1])%4]){ r[cur-1]=1; dfs(cur-1); } } if(cur%3!=2){//右 if(!r[cur+1])if(st[cur][(6-s[cur])%4]&&st[cur+1][(4-s[cur+1])%4]){ r[cur+1]=1; dfs(cur+1); } } } //旋转函数,返回旋转后状态 int rota(int x,int t){ memset(r,0,sizeof(r)); int tmp=x; for(int i=8;i>=0;i--){ s[i]=tmp%4; tmp/=4; } r[t]=1; dfs(t); int re=0; for(int i=0;i<9;i++){ if(!r[i])continue; if(abs(t-i)&1){ s[i]+=3; }else{ s[i]++; } s[i]%=4; } for(int i=0;i<9;i++){ re*=4; re+=s[i]; } return re; } int main(){ int t; cin>>t; while(t--){ //init memset(dis,0,sizeof(dis)); memset(match,0,sizeof(match)); //input for(int i=0;i<3;i++){ for(int k=0;k<8;k++){ for(int j=0;j<3;j++){ scanf("%s",G[i*3+j][k]); } } } for(int i=0;i<3;i++){ for(int k=0;k<8;k++){ for(int j=0;j<3;j++){ scanf("%s",G2[i*3+j][k]); } } } // for(int i=0;i<9;i++){ for(int j=0;j<4;j++){ scanf("%d",&st[i][j]); } } // bool ok; bool hasans=1; int ans=INF; for(int k=0;k<9;k++){ //0 ok=1; for(int i=0;i<8;i++){ for(int j=0;j<8;j++){ if(G[k][i][j]!=G2[k][i][j])ok=0; } } if(ok)match[k][0]=1; //90 ok=1; for(int i=0;i<8;i++){ for(int j=0;j<8;j++){ if(G[k][7-j][i]!=G2[k][i][j])ok=0; } } if(ok)match[k][1]=1; //180 ok=1; for(int i=0;i<8;i++){ for(int j=0;j<8;j++){ if(G[k][7-i][7-j]!=G2[k][i][j])ok=0; } } if(ok)match[k][2]=1; //270 ok=1; for(int i=0;i<8;i++){ for(int j=0;j<8;j++){ if(G[k][j][7-i]!=G2[k][i][j])ok=0; } } if(ok)match[k][3]=1; if(match[k][0]+match[k][1]+match[k][2]+match[k][3]==0){ hasans=0;break; } } if(!hasans){ cout<<-1<<endl; continue; } queue<int> que; que.push(0); dis[0]=1; if(judge(0)){ cout<<0<<endl; continue; } while(!que.empty()){ int cur=que.front(); que.pop(); for(int i=0;i<9;i++){ int news=rota(cur,i); if(!dis[news]){ dis[news]=dis[cur]+1; if(judge(news)){ ans=dis[cur]; break; } que.push(news); } } if(ans!=INF)break; } if(ans==INF){ cout<<-1<<endl; }else{ cout<<ans<<endl; } } return 0; }
相关文章推荐
- zoj 3814 Sawtooth Puzzle(搜索-bfs)
- BFS ZOJ 3814 Sawtooth Puzzle
- zoj 3814 Sawtooth Puzzle(隐式图搜索)
- ZOJ 3814 Sawtooth Puzzle (2014年牡丹江赛区网络赛F题)
- ZOJ 3814 Sawtooth Puzzle(牡丹江网络赛F题)
- ZOJ 3814 Sawtooth Puzzle 状态压缩搜索
- ZOJ - 3814 Sawtooth Puzzle
- ZOJ 3814 / 2014 牡丹江赛区网络赛 F. Sawtooth Puzzle
- ZOJ 3814 Sawtooth Puzzle (2014年牡丹江赛区网络赛F题)
- ZOJ 3814 Sawtooth Puzzle BFS
- 【数论-莫比乌斯】SPOJ-7001-Visible Lattice Points 、zoj 3435 Ideal Puzzle Bobble
- ZOJ3541-The Last Puzzle 区间dp
- ZOJ 3435 Ideal Puzzle Bobble(莫比乌斯反演)
- Zoj 3541 The Last Puzzle (dp) - 2011 ACM-ICPC Dalian Regional Contest Problem C
- ZOJ 3541-The Last Puzzle(区间DP)
- ZOJ 3814:模拟和状态压缩BFS
- zoj 3541 The Last Puzzle
- ZOJ_Multiplication Puzzle DP
- ZOJ 3541 The Last Puzzle(经典区间dp)
- ZOJ 3435 Ideal Puzzle Bobble(gcd(i,j,k)=1/莫比乌斯反演)