移动玩具[HAOI2008]
题目描述
在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移动到某人心中的目标状态。
输入
前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。接着是一个空行。接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。
输出
一个整数,所需要的最少移动次数。
样例输入
1111
0000
1110
0010
1010
0101
1010
0101
样例输出
4
题解
今天的排名是几天以来最高的,出分之前却十分难过。只打了一道半题,剩下两道敲不出正解打不出暴力,不出所料地两题爆零,意料之外地把我最好预估可能拿到的分数全部拿到了。调第一题的BFS良久,刚开始因为某些乱七八糟的错误一直运行错误,后来持续时间超限,意识到用我的想法不应该DFS后改成BFS又一直输出0,心力交瘁一直到十点左右调出样例内心感慨万分。期间多次想扔掉这题去打一打别的题,可是其他题实在不知道应该怎么做,索性一直调下去。之后第三题捡起我打了一半的暴力,优化了一下一开始超时的spfa,只求过掉前5个点。最高估分是150,最低就不好说了,比起昨天80-150的估分心理虚了不少,中午睡觉一直辗转反侧醒了好几次。但最后得了150,只能说我那三个小时没有白调,但是这样的事绝不会在正规考试中发生。毫无思路的第二题和第三题也告诉我基础实在还很不行,要学的、要复习的都很多,时间宝贵啊。
一看只有4*4的01矩阵,就觉得这题天生适合搜索,而且很可能搜出正解。二进制处理一下,开开心心开始dfs。刚开始二进制各种错乱,各种核实各种优化却发现这种搜索根本停不下来。忽然意识到DFS会把一种情况搜到底,可是它可能根本不是在往正确的方向走,想起最优解应该用BFS,又开始改成BFS。平常几乎不怎么用BFS,在取出队列中元素的时候又把while写成了if,导致结果一直是0满头雾水。终于改过了这一堆错,两个半个小时已经过去了,后面三道题一分没得,看见那个样例输出真是如释重负。这次考试一方面是因为后面的题不会做,另一方面是因为调这道题时间太长,虽然A掉了但还是非常虚。考试是过程也是经验,考试是一种有趣的经历,不管得到的是快乐还是苦恼。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int lx[5],xs[5],temp,dd[18][18][18][18]; char a1[5]; void init() { memset(dd,0x7f,sizeof(dd)); for(int i=1;i<=4;i++) { scanf("%s",a1); for(int j=1;j<=4;j++) { temp=a1[4-j]-'0'; if(temp) xs[i]=xs[i]|(1<<(j-1)); } } for(int i=1;i<=4;i++) { scanf("%s",a1); for(int j=1;j<=4;j++) { temp=a1[4-j]-'0'; if(temp) lx[i]=lx[i]|(1<<(j-1)); } } } int jg,tp; void bj(int &x,int y) { x=x<y?x:y; } struct ZT { int x1,x2,x3,x4,bz; }zt; queue<ZT> q; bool cj=0; void ss(int x1,int x2,int x3,int x4,int bz) { if(x1==lx[1]&&x2==lx[2]&&x3==lx[3]&&x4==lx[4]) { jg=bz; cj=1; return; } if(cj) return; if(dd[x1][x2][x3][x4]<=bz) return; dd[x1][x2][x3][x4]=bz; int cl; for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) { cl=4-j; if(i==1) if(x1&(1<<cl)) { if(j!=1&&!(x1&(1<<(cl+1)))) { temp=x1|(1<<(cl+1)); temp=temp&(~(1<<cl)); zt.x1=temp; zt.x2=x2; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(j!=4&&!(x1&(1<<(cl-1)))) { temp=x1|(1<<(cl-1)); temp=temp&(~(1<<cl)); zt.x1=temp; zt.x2=x2; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(!(x2&(1<<cl))) { temp=x2|(1<<cl); tp=x1&(~(1<<cl)); zt.x1=tp; zt.x2=temp; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } } if(i==2) if(x2&(1<<cl)) { if(j!=1&&!(x2&(1<<(cl+1)))) { temp=x2|(1<<(cl+1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=temp; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(j!=4&&!(x2&(1<<(cl-1)))) { temp=x2|(1<<(cl-1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=temp; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(!(x3&(1<<cl))) { temp=x3|(1<<cl); tp=x2&(~(1<<cl)); zt.x1=x1; zt.x2=tp; zt.x3=temp; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(!(x1&(1<<cl))) { temp=x1|(1<<cl); tp=x2&(~(1<<cl)); zt.x1=temp; zt.x2=tp; zt.x3=x3; zt.x4=x4; zt.bz=bz+1; q.push(zt); } } if(i==3) if(x3&(1<<cl)) { if(j!=1&&!(x3&(1<<(cl+1)))) { temp=x3|(1<<(cl+1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=temp; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(j!=4&&!(x3&(1<<(cl-1)))) { temp=x3|(1<<(cl-1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=temp; zt.x4=x4; zt.bz=bz+1; q.push(zt); } if(!(x4&(1<<cl))) { temp=x4|(1<<cl); tp=x3&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=tp; zt.x4=temp; zt.bz=bz+1; q.push(zt); } if(!(x2&(1<<cl))) { temp=x2|(1<<cl); tp=x3&(~(1<<cl)); zt.x1=x1; zt.x2=temp; zt.x3=tp; zt.x4=x4; zt.bz=bz+1; q.push(zt); } } if(i==4) if(x4&(1<<cl)) { if(j!=1&&!(x4&(1<<(cl+1)))) { temp=x4|(1<<(cl+1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=x3; zt.x4=temp; zt.bz=bz+1; q.push(zt); } if(j!=4&&!(x4&(1<<(cl-1)))) { temp=x4|(1<<(cl-1)); temp=temp&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=x3; zt.x4=temp; zt.bz=bz+1; q.push(zt); } if(!(x3&(1<<cl))) { temp=x3|(1<<cl); tp=x4&(~(1<<cl)); zt.x1=x1; zt.x2=x2; zt.x3=temp; zt.x4=tp; zt.bz=bz+1; q.push(zt); } } } while(!q.empty()) { x1=q.front().x1; x2=q.front().x2; x3=q.front().x3; x4=q.front().x4; bz=q.front().bz; q.pop(); ss(x1,x2,x3,x4,bz); } } int main() { init(); ss(xs[1],xs[2],xs[3],xs[4],0); printf("%d",jg); return 0; }
这代码有毒= =7K呀水题
南风知我意,吹梦到西洲。