題外話:昨夜腦子昏沉,今早一調試就過了...錯誤有:我忘記還有墻直接穿墻過...memset初始化INF用錯了數...然后手殘敲錯一個狀態一直過不了樣例...要是這狀態去比賽我簡直完了......orz
題目鏈接:https://www.luogu.org/problemnew/show/P4011
?

輸入輸出樣例
輸入樣例#1:
4 4 9 9 1 2 1 3 2 1 2 2 2 0 2 1 2 2 0 2 1 3 1 0 2 3 3 3 0 2 4 3 4 1 3 2 3 3 0 3 3 4 3 0 4 3 4 4 0 2 2 1 2 4 2 1
輸出樣例#1:
14

?
題解:分層圖最短路問題。最多就10類門,一看就是狀態壓縮最大空間 (1<<11)-1 ,很友好...d[i][sta]表示到點i,狀態為sta的最短路長度(sta就是到i點前所持有的鑰匙的狀態)。
代碼:


1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 #include <queue> 5 #include <cstring> 6 #define CLR(a, b) memset((a), (b), sizeof((a))) 7 using namespace std; 8 const int N = 110; 9 const int states = 1<<11; 10 const int INF = 0x3f3f3f3f; 11 12 int d[N][states], vis[N][states]; 13 int id[N][N]; 14 int key[N]; //key[i]:i點有哪些鑰匙(狀態) 15 int mp[N][N]; //mp[i][j]:i到j有哪類門 16 int dx[] = {1, 0, -1, 0}; 17 int dy[] = {0, 1, 0, -1}; 18 int n, m, p; 19 struct qnode{ 20 int v; 21 int x;//狀態 22 qnode(int _v=0,int _x=0):v(_v),x(_x){} 23 }; 24 bool SPFA(int st, int ed) { 25 CLR(vis, 0); 26 CLR(d, INF); 27 d[st][0] = 0; 28 queue<qnode> q; 29 while(!q.empty()) q.pop(); 30 q.push(qnode(st, 0)); 31 while(!q.empty()) { 32 qnode t = q.front(); q.pop(); 33 int u = t.v; 34 int sta = t.x; 35 vis[u][sta] = false; 36 37 if(key[u]) sta |= key[u]; 38 for(int i = 0; i < 4; i++) { 39 int x = (u+m-1)/m + dx[i]; 40 int y = (u%m?u%m:m) + dy[i]; 41 42 if(x < 1 || x > n || y < 1 || y > m) continue; 43 int v = id[x][y]; 44 //不是墻 并且 有對應鑰匙 或者沒有門。 45 if(mp[u][v]!=0 && ( (sta&(1<<mp[u][v])) || mp[u][v]==-1)) { 46 if(d[v][sta] > d[u][t.x] + 1) { 47 d[v][sta] = d[u][t.x] + 1; 48 if(!vis[v][sta]) { 49 vis[v][sta] = true; 50 q.push(qnode(v, sta)); 51 } 52 } 53 } 54 } 55 } 56 int ans = INF; 57 for(int i = 0; i < states; ++i) ans = min(ans, d[ed][i]); 58 if(ans == INF) puts("-1"); 59 else printf("%d\n", ans); 60 } 61 int main() { 62 int i, j, k, x1, y1, x2, y2, q, sum; 63 scanf("%d%d%d", &n, &m, &p);//行,列,門和墻的總數 64 65 int cnt = 0; 66 for(i = 1; i <= n; ++i) 67 for(j = 1; j <= m; ++j) id[i][j] = ++cnt; 68 69 CLR(mp, -1); 70 scanf("%d", &k);//門和墻總數 71 for(i = 1; i <= k; ++i) { 72 scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &q); 73 int id1 = id[x1][y1]; 74 int id2 = id[x2][y2]; 75 mp[id1][id2] = mp[id2][id1] = q; 76 } 77 scanf("%d", &sum);//鑰匙總數 78 for(i = 1; i <= sum; ++i) { 79 scanf("%d%d%d", &x1, &y1, &q); 80 key[id[x1][y1]] |= (1<<q); 81 } 82 SPFA(1, n*m); 83 return 0; 84 }
?