题意:为你两个状态,求a到b 的最小路径,要求字典序最小。
思路:
最开始想的是目标状态是变化的,所以打表应该不行,然后直接上A*,但是TLE了- -(瞬间无语)
然后看了下别人的思路,预处理出9个状态(好机智),然后打表。
因为x所在的位置只有9中,我们可以根据x的位置打表,而且不同的串可以等效替代
例: 564178x23 7568x4123
--> 123456x78 5126x3478
而且题目保证一定会有解。 所以bfs+打表,至于双向bfs,写了发现一直cuo,后来发现在反向搜索时很难保证最小字典序,如果有两条路走到同一个节点,你就要比较它们长短,一样则比大小
问题:
①没考虑到a = b时的情况(果然很水)
②a = b时后面还有空行- -,也是醉的不行
③考虑不够全面,一开始就把打表这个排除了,
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> typedef long long ll; using namespace std; const int maxn = 3700000; int fac[] = {1,1,2,6,24,120,720,5040,40320,362880}; int vis[10][maxn]; struct node { int matrix[10]; int position; int state; }; int cantor(int s[]) { int sum = 0; for(int i = 0; i < 9; i ++) { int num = 0; for(int j = i+1; j < 9; j++) if(s[j] < s[i]) num++; sum += (num*fac[9-i-1]); } return sum + 1; } struct node2 { int pre; char ch; } pre[10][maxn]; char dire[5]="dlru"; int dir[4] = {3,-1,1,-3}; node cur; void bfs(int t) { queue<node>q; vis[t][cur.state] = 1; int tnum = 1; pre[t][1].pre = -1; q.push(cur); while(!q.empty()) { cur = q.front(); q.pop(); for(int i = 0; i < 4; i++) { if(i==3&&cur.position<3)continue; if(i==2&&cur.position%3==2)continue; if(i==0&&cur.position>5)continue; if(i==1&&cur.position%3==0)continue; node tmp = cur; tmp.position = cur.position + dir[i]; tmp.matrix[cur.position] = tmp.matrix[tmp.position]; tmp.matrix[tmp.position] = 0; tmp.state = cantor(tmp.matrix); if(!vis[t][tmp.state]) { vis[t][tmp.state] = ++tnum; pre[t][tnum].ch = dire[i]; pre[t][tnum].pre = vis[t][cur.state]; q.push(tmp); } } } return ; } int all; void pri(int t,int k) { if(pre[t][k].pre == -1) { printf("%d ",all); return; } all++; pri(t,pre[t][k].pre); printf("%c",pre[t][k].ch); } void get_(int k) { int tot = 0; for(int i = 0; i < 9; i++) { if(i == k) continue; else cur.matrix[i] = ++tot; } cur.matrix[k] = 0; cur.position = k; cur.state = cantor(cur.matrix); } int num[10]; int main() { get_(0); bfs(0); get_(1); bfs(1); get_(2); bfs(2); get_(3); bfs(3); get_(4); bfs(4); get_(5); bfs(5); get_(6); bfs(6); get_(7); bfs(7); get_(8); bfs(8); node from,to; int cas = 1; int n; scanf("%d",&n); char a[10]; char b[10]; while(n--) { scanf("%s",a); scanf("%s",b); printf("Case %d: ",cas++); int posi; for(int i = 0,j = 0; i < strlen(a); i++) { if(a[i] == 'x' || a[i] == 'X') posi = i; else num[a[i]-'0'] = j++; } for(int i = 0; i < strlen(b); i++) { if(b[i] == 'x' || b[i] == 'X') { from.position = i; from.matrix[i] = 0; } else { from.matrix[i] = num[b[i]-'0']+1; } } from.state = cantor(from.matrix); if(!strcmp(a,b)) { printf("0 "); printf(" "); continue; } // for(int i = 0; i < 9; i++) // printf("%d ",from.matrix[i]); // // printf("%d",from.state); all = 0; pri(posi,vis[posi][from.state]); printf(" "); } return 0; }