http://acm.hust.edu.cn/vjudge/contest/view.action?cid=81769#problem/E
/** UVALive 6665 最短路 题目大意:给定一个3*3的棋盘,里面有8个现有的棋子,然后移动棋子,从初始状态到目标状态最少花费是多少? 解题思路:这个题用bfs+康托展开写的结果超时,后来从网上学了一个最短路的写法,速度很快。每种状态压缩成一个整数,每种状态间进行建边, 然后对于每组给定的起止状态求最短路即可 */ #include <iostream> #include <cstdio> #include <queue> #include <algorithm> #include <cstring> #include <cstdio> #include <iostream> #define maxn 500005 #define inf 10000000 using namespace std; int fac[10] = {1,1,2,6,24,120,720,5040,40320,362880}; void Atoint(int* a, int &x) { int i, j, y; x = 0; for (i = 0; i < 9; i++) { y = a[i]; for (j = 0; j < i; j++) if (a[j] < a[i]) y--; x += fac[8 - i] * y; } } void inttoA(int x, int* a) { int has[10] = {0}; int i, j, y; for (i = 0; i < 9; i++) { y = x / fac[8 - i]; for (j = 0; j < 9; j++) if (!has[j]) { if (y == 0) break; y--; } a[i] = j, has[j] = 1, x %= fac[8 - i]; } } int head[maxn],ip; int ch,cv,start,target,MaxIndex; void init() { memset(head,-1,sizeof(head)); ip=0; } struct note { int v,w,next; } edge[maxn*4]; void addedge(int u,int v,int w) { edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++; } struct node { int d,u; node() {} node(int x,int y) { d=x, u=y; } bool operator <(const node & other) const { return d>other.d; } }; bool vis[maxn]; int d[maxn]; int Dij(int s,int t) { priority_queue<node> Q; for(int i=0; i<=MaxIndex; i++) d[i] = inf; d[s] = 0; memset(vis,false,sizeof(vis)); Q.push(node(0,s)); while(!Q.empty()) { node x = Q.top(); Q.pop(); int u = x.u; if(u == t) return d[u]; if(vis[u]) continue; vis[u] = true; for(int i = head[u]; i!=-1 ; i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; if(w)w=cv; else w=ch; if(d[v]>d[u]+w) { d[v] = d[u]+w; Q.push(node(d[v],v)); } } } } int a[9]= {8,7,6,5,4,3,2,1,0}; int main() { init(); Atoint(a,MaxIndex); ///printf("MaxIndex=%d\n",MaxIndex); for(int i=0; i<=MaxIndex; i++) { inttoA(i,a); int j,y; for(j=0; j<9; j++) { if(a[j]==0) break; } swap(a[j],a[(j+1)%9]); Atoint(a,y); addedge(i,y,0); swap(a[j],a[(j+1)%9]); swap(a[j],a[(j+8)%9]); Atoint(a,y); addedge(i,y,0); swap(a[j],a[(j+8)%9]); swap(a[j],a[(j+3)%9]); Atoint(a,y); addedge(i,y,1); swap(a[j],a[(j+3)%9]); swap(a[j],a[(j+6)%9]); Atoint(a,y); addedge(i,y,1); swap(a[j],a[(j+6)%9]); } while(~scanf("%d%d",&ch,&cv)) { if(ch == 0 && cv == 0) break; for(int i=0; i<9; i++) scanf("%d",&a[i]); Atoint(a,start); for(int i=0; i<9; i++) scanf("%d",&a[i]); Atoint(a,target); printf("%d\n",Dij(start,target)); } return 0; } ///=================================== /**超时代码 #include<map> #include<set> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<string> #include<fstream> #include<cstring> #include<ctype.h> #include<iostream> #include<algorithm> #define maxn 1000 #define INF (1<<30) #define PI acos(-1.0) #define mem(a, b) memset(a, b, sizeof(a)) #define For(i, n) for (int i = 0; i < n; i++) #define debug puts("===============") const int N = 362881; typedef long long ll; using namespace std; int ch, cv; int fac[10]; struct node { int x, w; node(int _x, int _w) { x = _x, w = _w; } bool operator < (const node & T) const { return w > T.w; } }; void Atoint(int* a, int &x) { int i, j, y; x = 0; for (i = 0; i < 9; i++) { y = a[i]; for (j = 0; j < i; j++) if (a[j] < a[i]) y--; x += fac[8 - i] * y; } } void inttoA(int x, int* a) { int has[10] = {0}; int i, j, y; for (i = 0; i < 9; i++) { y = x / fac[8 - i]; for (j = 0; j < 9; j++) if (!has[j]) { if (y == 0) break; y--; } a[i] = j, has[j] = 1, x %= fac[8 - i]; } } int st, ed; priority_queue<node> q; int d[N], vis[N], a[10], b[10]; void update(int x, int w) { if (!vis[x] && d[x] > w) { d[x] = w, q.push(node(x, w)); } } void work() { Atoint(a, st), Atoint(b, ed); while(!q.empty()) q.pop(); memset(d, 0x7F, sizeof(d)); memset(vis, 0, sizeof(vis)); d[st] = 0; q.push(node(st, 0)); int x, w, i, y; while(!q.empty()) { x = q.top().x, w = q.top().w, q.pop(); if (vis[x]) continue; vis[x] = 1; if (x == ed) { printf("%d\n", w); break; } inttoA(x, a); for (i = 0; i < 9; i++) if (!a[i]) break; swap(a[i], a[(i + 1) % 9]); Atoint(a, y); update(y, w + ch); swap(a[i], a[(i + 1) % 9]); swap(a[i], a[(i + 8) % 9]); Atoint(a, y); update(y, w + ch); swap(a[i], a[(i + 8) % 9]); swap(a[i], a[(i + 3) % 9]); Atoint(a, y); update(y, w + cv); swap(a[i], a[(i + 3) % 9]); swap(a[i], a[(i + 6) % 9]); Atoint(a, y); update(y, w + cv); } } int main () { //freopen("1.txt", "r", stdin); fac[0] = 1; for (int i = 1; i < 10; i++) fac[i] = fac[i - 1] * i; while(scanf("%d%d", &ch, &cv), ch || cv) { for (int i = 0; i < 9; i++) scanf("%d", a + i); for (int i = 0; i < 9; i++) scanf("%d", b + i); work(); } return 0; }*/