好吧,我承认,我屈服了,那个题(ZOJ1245 || POJ1471)我现在实在写不出来,那就换题吧……
我找到了这个题,不为别的,就因为它描述短……
但其实人家不好欺负的,弄懂题意好难啊……
开始一直不明白题意,我就不明白了那个实例是咋来的,后来在帖子区看到一位前辈提示,一针见血,于是就明白了题意:
是说有一张图,上面的路径都是着色的,开始的时候有3个盘子在确定的点上,现在让你按要求沿图中的路径移动盘子(一步只能移动一只盘子),问是否能将3个盘子都移到同一个点上,如果可以,输出需要的最少步数,否则输出“impossible”。
注意这句话:The following constraint is imposed on this: the piece may only be moved along arrows of the same colour as the arrow between the two opponents' pieces.
意思是,每个盘子只能沿着这样一条路移动,这条路的颜色和另外的两个盘子之间的路径上标记的颜色是一样的。
当然,这道题给的是完全图,也就是说图上每两个点之间都有路径存在,它们标记的都有颜色。
思路嘛,不是我想出来的,是看了人家的说,bfs爆解……
代码的原创性也不是很高,这个是因为我觉得那哥们的 bfs() 写的好风骚,于是就果断放弃自己冗长的代码,照着人家的写的
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define N 60 struct node { int a,b,c; int time; }cur,next; int mark[N][N][N],n;//mark[][][]保存当前时刻3个盘子所在位置 char map[N][N]; int bfs() { int i; queue<node> q; memset(mark,0,sizeof(mark)); cur.time=0; mark[cur.a][cur.b][cur.c]=1; if(cur.a==cur.b && cur.b==cur.c)return 0; q.push(cur); while(!q.empty()) { cur=q.front(); q.pop(); for(i=1;i<=n;i++) { if(map[cur.a][i]==map[cur.b][cur.c] && !mark[i][cur.b][cur.c]) {//对图中每个点遍历,满足条件的就入队,并将这种状态标记,避免重复操作 mark[i][cur.b][cur.c]=1; next.time=cur.time+1; next.a=i, next.b=cur.b, next.c=cur.c; if(next.a==next.b && next.b==next.c) return next.time; q.push(next); } if(map[cur.b][i]==map[cur.a][cur.c] && !mark[cur.a][i][cur.c]) { mark[cur.a][i][cur.c]=1; next.time=cur.time+1; next.a=cur.a, next.b=i, next.c=cur.c; if(next.a==next.b && next.b==next.c) return next.time; q.push(next); } if(map[cur.c][i]==map[cur.b][cur.a] && !mark[cur.a][cur.b][i]) { mark[cur.a][cur.b][i]=1; next.time=cur.time+1; next.a=cur.a, next.b=cur.b, next.c=i; if(next.a==next.b && next.b==next.c) return next.time; q.push(next); } } } return -1; } int main() { int i,j; while(scanf("%d",&n),n) { scanf("%d%d%d",&cur.a,&cur.b,&cur.c); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) cin>>map[i][j];//cin的确很好用的说…… } int x=bfs(); if(x!=-1) printf("%d/n",x); else printf("impossible/n"); } return 0; }