http://poj.org/problem?id=1184
用字符串s存下数字,并把光标位置做一个字符加到s末尾,用map做标记状态是否出现过,然后bfs即可。
不剪枝是过不了的,考虑的两种交换操作都不涉及到2,3,4,5位置,所以这几个位置只能通过up,down来改变。
如果这几个位置是和目标状态是不一样的,那肯定是用up,down操作是最优的,而不会执行left,right操作。
所以这几个位置只有在和目标状态一样时做left,right操作。
#include <iostream> #include <map> #include <string> #include <queue> using namespace std; struct point { int step; string s; }; string e; map<string,int> my; queue<point> q; int BFS(point st) { point t,tt; string ss; int i; while(!q.empty()) q.pop(); q.push(st); my[st.s]=1; while(!q.empty()) { t=q.front(); q.pop(); for(ss=t.s,i=0;i<6;i++) if(ss[i]!=e[i]) break; if(i==6) return t.step; ss=t.s; swap(ss[0],ss[ss[6]-'0']);//Swap0: if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } ss=t.s; swap(ss[5],ss[ss[6]-'0']); //Swap1 if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } ss=t.s; if(ss[ss[6]-'0']!='9'&&ss[ss[6]-'0']!=e[ss[6]-'0']) ss[ss[6]-'0']+=1; //Up: if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } ss=t.s; if(ss[ss[6]-'0']!='0'&&ss[ss[6]-'0']!=e[ss[6]-'0']) ss[ss[6]-'0']-=1;//Down: if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } ss=t.s; if(ss[6]-'0'!=0)//left { if(ss[6]!='5') //1 2 3 4位置相同才能移动光标 { if(ss[ss[6]-'0']==e[ss[6]-'0']) ss[6]-=1; } else ss[6]-=1; } if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } ss=t.s; if(ss[6]-'0'!=5)//Right { if(ss[6]!='0') //1 2 3 4位置相同才能移动光标 { if(ss[ss[6]-'0']==e[ss[6]-'0']) ss[6]+=1; } else ss[6]+=1; } if(!my.count(ss)) { tt.s=ss; tt.step=t.step+1; q.push(tt); my[ss]=1; } } } int main(int argc, char *argv[]) { point st; while(cin>>st.s>>e) { my.clear(); st.s+='0'; st.step=0; cout<<BFS(st)<<endl; } return 0; }