题目链接:Eight
解题思路:原来不知道,这是有名的8数码问题,它还用和15数码来废话半天。看了眼过的人数,直接BFS肯定就T了,况且,状态总数是9!, 36W,我怎么都不会估算复杂度了,这不是很少的状态么怎么还会TLE。
后来有人说打表,就是从终点向其他状态扩展同时记录操作序列,然后全部存到map里面,我看也有人用康托展开就存下了,其实map更简单。
还有无解的情况,其实就是逆序数的问题,终止节点的逆序数是0,然后你用空白节点和左右两边交换的话逆序数是不变的,那就只有上下了
我们分析a b c *这种情况,另一种是相反的。a和*互换
大小顺序
a b c
+2 0 0
a c b
+2 0 0
b a c
-1 +1 0
b c a
-1 -1 0
c a b
-1 +1 0
c b a
-1 -1 0
我们看到逆序数只有+2,+0,-2所以,逆序数只能为偶数,这也就是题目上面为什么说交换之后就无解了,那是因为交换两个相邻的数的话,逆序数不是+1就是-1,会从偶数变到奇数,从奇数变到偶数。就成无解了。
这是我在线打表的程序,打表差不多要650+MS左右。
#include<cstdio> #include<map> #include<queue> #include<string> #include<iostream> using namespace std; struct node{ int s, idx; string seq; node(){} node(int ss, int iidx, string sseq){ s = ss, seq = sseq, idx = iidx; } }; int pp[10] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; map<int, string> ans; string put[4] = {"d","u","r","l"}; int dir[9][4] = {{-1,3,-1,1},{-1,4,0,2},{-1,5,1,-1},{0,6,-1,4},{1,7,3,5},{2,8,4,-1},{3,-1,-1,7},{4,-1,6,8},{5,-1,7,-1}}; int getA(int s, int idx){ return s / pp[idx] % 10; } int change(int s, int a, int b){ a = 8 - a; b = 8 - b; int tem = getA(s, a); s -= tem * pp[a]; s += getA(s, b) * pp[a]; s -= getA(s, b) * pp[b]; s += tem * pp[b]; return s; } void bfs(){ int i, j, k; queue<node> mq; mq.push(node(123456789, 8, "")); ans[123456789] = "YES"; while(!mq.empty()){ node s = mq.front(); //cout << s.s << " " << s.idx << " " << s.seq << endl; mq.pop(); for(i = 0; i < 4; i++){ int ss = s.s; int ii = s.idx; string qq = s.seq; qq += put[i]; int tem = dir[ii][i]; if(tem == -1) continue; ss = change(ss, tem, ii); if(ans[ss] == ""){ ans[ss] = qq; mq.push(node(ss, tem, qq)); } } } } char ac[100]; int main(){ int i, j, k; // freopen("1.out", "w", stdout); //freopen("1.in", "r", stdin); bfs(); /*for(map<int, string>::iterator it = ans.begin(); it != ans.end(); it++){ cout << it->first << " " << it->second << endl; }*/ while(gets(ac)){ int s = 0, tot = 0; for(i = 0; tot < 9; i++){ if(ac[i] >= '1' && ac[i] <= '8'){ s = s * 10 + ac[i] - '0'; tot++; } if(ac[i] == 'x'){ s = s * 10 + 9; tot++; } } if(ans[s] == "YES"){ puts(""); } else if(ans[s] == ""){ puts("unsolvable"); } else{ string tem = ans[s]; for(i = tem.length() - 1; i >= 0; i--){ printf("%c", tem[i]); } printf("\n"); } } return 0; }