SPOJ KATHTHI - KATHTHI
以前并不知道这个trick。
$01BFS$,在$bfs$的时候用一个双端队列来维护,如果边权为$1$就添加到队尾,边权为$0$就添加到队首。
还有一个小trick就是我们可以开一个$dis$数组来代替$vis$数组做类似于$dp$的操作,因为双端插入的特性使$vis$的表示可能产生歧义,每一次能更新$dis$即入队,这样子也刚好对应了最短路的意义。
时间复杂度$O(Tn^2)$。
Code:
#include <cstdio> #include <cstring> #include <deque> using namespace std; const int N = 1005; const int dx[] = {1, 0, -1, 0}; const int dy[] = {0, 1, 0, -1}; int testCase, n, m, dis[N][N]; char mp[N][N]; struct Node { int x, y, stp; inline Node(int nowX = 0, int nowY = 0, int nowStp = 0) { x = nowX, y = nowY, stp = nowStp; } }; deque <Node> Q; inline bool valid(Node now) { return now.x >= 1 && now.x <= n && now.y >= 1 && now.y <= m; } int bfs() { if(n == 1 && m == 1) return 0; memset(dis, 0x3f, sizeof(dis)); dis[1][1] = 0; Q.clear(); Q.push_back(Node(1, 1, 0)); for(; !Q.empty(); ) { Node out = Q.front(); Q.pop_front(); for(int i = 0; i < 4; i++) { Node in = Node(out.x + dx[i], out.y + dy[i], 0); if(!valid(in)) continue; if(dis[in.x][in.y] <= dis[out.x][out.y] + (mp[out.x][out.y] != mp[in.x][in.y])) continue; dis[in.x][in.y] = dis[out.x][out.y] + (mp[out.x][out.y] != mp[in.x][in.y]); in.stp = dis[in.x][in.y]; if(in.stp == out.stp) Q.push_front(in); else Q.push_back(in); } } } int main() { for(scanf("%d", &testCase); testCase--; ) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%s", mp[i] + 1); bfs(); printf("%d\n", dis[n][m]); /* for(int i = 1; i <= n; i++, printf("\n")) for(int j = 1; j <= m; j++) printf("%c ", mp[i][j]); printf("\n"); for(int i = 1; i <= n; i++, printf("\n")) for(int j = 1; j <= m; j++) printf("%d ", vis[i][j]); */ } return 0; }