从刘汝佳训练指南上看到的一道题,看了解释之后发现是一道最短路问题,(x,y,d,c)表示位于(x,y)点面向为d,颜色为c的状态,然后每个状态有左转,右转,前进3个转移方式也就对应三条边,然后建图求最短路就可以了。
代码:
1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <climits> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <map> 9 #include <cmath> 10 #include <vector> 11 #include <queue> 12 #include <algorithm> 13 #define esp 1e-6 14 #define pb push_back 15 #define in freopen("in.txt", "r", stdin); 16 #define out freopen("out.txt", "w", stdout); 17 #define print(a) printf("%d\n",(a)); 18 #define bug puts("********))))))"); 19 #define stop system("pause"); 20 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) 21 #define inf 0x0f0f0f0f 22 using namespace std; 23 typedef long long LL; 24 typedef vector<int> VI; 25 typedef pair<int, int> pii; 26 typedef vector<pii,int> VII; 27 typedef vector<int>:: iterator IT; 28 const int maxn = 100000; 29 const int maxm = 60*25*25+100; 30 struct EDGE 31 { 32 int i, c; 33 EDGE *next, *ani; 34 } *Edge[maxn], E[maxm]; 35 int cnt = 0; 36 int src; 37 int R, C; 38 int node[30][30][10][10]; 39 int dx[] = {-1, 0, 1, 0}; 40 int dy[] = {0, 1, 0, -1}; 41 int dis[maxn], inq[maxn]; 42 char maze[30][30]; 43 void add(int i, int j, int c, EDGE &e1) 44 { 45 e1.i = j, e1.next = Edge[i], e1.c = c, Edge[i] = &e1; 46 cnt++; 47 } 48 void init(void) 49 { 50 cnt = 0; 51 memset(Edge, 0, sizeof(Edge)); 52 } 53 void spfa(int ss) 54 { 55 memset(inq, 0, sizeof(inq)); 56 memset(dis, 0x0f, sizeof(dis)); 57 dis[ss] = 0; 58 queue<int> q; 59 inq[ss] = 1; 60 q.push(ss); 61 while(!q.empty()) 62 { 63 int u = q.front(), v; 64 q.pop(); 65 inq[u] = 0; 66 for(EDGE *p = Edge[u]; p; p = p->next) 67 { 68 // print(p->i) 69 if(dis[v = p->i] > dis[u] + p->c) 70 if(dis[v] = dis[u] + p->c, !inq[v]) 71 inq[v] = 1, q.push(v); 72 } 73 } 74 } 75 void build_graph() 76 { 77 for(int i = 0; i < R; i++) 78 for(int j = 0; j < C; j++) 79 if(maze[i][j] == '.') 80 for(int k = 0; k < 4; k++) 81 for(int l = 0; l < 5; l++) 82 { 83 int u = node[i][j][k][l], v; 84 v = node[i][j][(k - 1 + 4)%4][l]; 85 add(u, v, 1, E[cnt]); 86 v = node[i][j][(k + 1)%4][l]; 87 add(u, v, 1, E[cnt]); 88 int ii = i + dx[k]; 89 int jj = j + dy[k]; 90 if(ii >= 0 && ii < R && jj >= 0 && jj < C && maze[ii][jj] == '.') 91 { 92 v = node[ii][jj][k][(l+1)%5]; 93 add(u, v, 1, E[cnt]); 94 } 95 } 96 } 97 int main(void) 98 { 99 int t = 1; 100 for(int i = 0; i < 30; i++) 101 for(int j = 0; j < 30; j++) 102 for(int k = 0; k < 10; k++) 103 for(int l = 0; l < 10; l++) 104 node[i][j][k][l] = i*(30*10*10)+j*(10*10)+k*10+l; 105 while(scanf("%d%d", &R, &C), R||C) 106 { 107 init(); 108 int sx, sy, tx, ty; 109 for(int i = 0; i < R; i++) 110 { 111 scanf("%s", maze[i]); 112 for(int j = 0; j < C; j++) 113 if(maze[i][j] == 'S') 114 { 115 sx = i; 116 sy = j; 117 maze[i][j] = '.'; 118 } 119 else if(maze[i][j] == 'T') 120 { 121 tx = i; 122 ty = j; 123 maze[i][j] = '.'; 124 } 125 } 126 build_graph(); 127 src = node[sx][sy][0][0]; 128 spfa(src); 129 int ans = inf; 130 for(int k = 0; k < 4; k++) 131 { 132 int end = node[tx][ty][k][0]; 133 ans = min(ans, dis[end]); 134 } 135 if(t - 1) 136 puts(""); 137 printf("Case #%d\n", t); 138 t++; 139 if(ans == inf) 140 puts("destination not reachable"); 141 else printf("minimum time = %d sec\n", ans); 142 } 143 return 0; 144 }
下面是汝佳神牛的代码,不禁感叹真是一目了然啊。、
1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <climits> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <map> 9 #include <cmath> 10 #include <vector> 11 #include <queue> 12 #include <algorithm> 13 #define esp 1e-6 14 #define pb push_back 15 #define in freopen("in.txt", "r", stdin); 16 #define out freopen("out.txt", "w", stdout); 17 #define print(a) printf("%d\n",(a)); 18 #define bug puts("********))))))"); 19 #define stop system("pause"); 20 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) 21 #define inf 0x0f0f0f0f 22 using namespace std; 23 typedef long long LL; 24 typedef vector<int> VI; 25 typedef pair<int, int> pii; 26 typedef vector<pii,int> VII; 27 typedef vector<int>:: iterator IT; 28 const int maxr = 25 + 5; 29 const int maxc = 25 + 5; 30 struct State 31 { 32 int r, c, dir, color; 33 State(int r, int c, int dir, int color): r(r), c(c), dir(dir), color(color) {} 34 }; 35 int R, C, ans; 36 int d[maxr][maxc][4][5], vis[maxr][maxc][4][5]; 37 char maze[maxr][maxc]; 38 int sr, sc, tr, tc; 39 int dr[] = {-1, 0, 1, 0}; 40 int dc[] = {0, 1, 0, -1}; 41 queue<State> q; 42 void update(int r, int c, int dir, int color, int v) 43 { 44 if(r <0 || r >= R || c < 0 || c >= C || maze[r][c] != '.' || vis[r][c][dir][color]) return; 45 vis[r][c][dir][color] = 1; 46 d[r][c][dir][color] = v; 47 q.push(State(r, c, dir, color)); 48 if(r == tr && c == tc && color == 0) 49 ans = min(ans, v); 50 } 51 void bfs(State st) 52 { 53 vis[st.r][st.c][st.dir][st.color] = 1; 54 d[st.r][st.c][st.dir][st.color] = 0; 55 q.push(st); 56 while(!q.empty()) 57 { 58 State st = q.front(); 59 q.pop(); 60 int v = d[st.r][st.c][st.dir][st.color] + 1; 61 update(st.r, st.c, (st.dir+3)%4, st.color, v); 62 update(st.r+dr[st.dir], st.c+dc[st.dir], st.dir, (st.color+1)%5, v); 63 update(st.r, st.c, (st.dir+1)%4, st.color, v); 64 } 65 } 66 int main(void) 67 { 68 69 int t = 1; 70 while(scanf("%d%d", &R, &C), C||R) 71 { 72 if(t - 1) 73 puts(""); 74 memset(vis, 0, sizeof(vis)); 75 for(int i = 0; i < R; i++) 76 { 77 scanf("%s", maze[i]); 78 for(int j = 0; j < C; j++) 79 if(maze[i][j] == 'S') 80 sr = i, sc = j; 81 else if(maze[i][j] == 'T') 82 tr = i, tc = j; 83 } 84 ans = inf; 85 maze[sr][sc] = maze[tr][tc] = '.'; 86 bfs(State(sr, sc, 0, 0)); 87 printf("Case #%d\n", t); 88 if(ans != inf) 89 printf("minimum time = %d sec\n", ans); 90 else puts("destination not reachable"); 91 t++; 92 } 93 return 0; 94 }