zoj 3814 Sawtooth Puzzle

来源:互联网 发布:c语言if else语句例子 编辑:程序博客网 时间:2024/05/16 15:17

        题意:9张正方形卡片摆成3*3,每张卡片有图案,求从当前状态旋转到目标状态的最短步。卡片的某些边类似齿轮,如果相邻的边都是齿轮边,它们就会同时旋转。

        思路:搜索。这个题比较复杂,涉及到好多问题,比如状态的编码解码,图像相同的校验,旋转的模拟等等。首先编码问题用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 100000000char 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--){//initmemset(dis,0,sizeof(dis));memset(match,0,sizeof(match));//inputfor(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++){//0ok=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;//90ok=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;//180ok=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;//270ok=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;}


0 0
原创粉丝点击