ACM
题目地址:SPOJ 206 BITMAP
题意:
给出一个矩阵,有黑白点,计算每个点离最近的白点的距离,p1=(i1,j1) and p2=(i2,j2),距离d(p1,p2)=|i1-i2|+|j1-j2|.
分析:
有剪枝的BFS,如果从黑色的开始进行BFS最近的白色,复杂度是O(n^4),复杂度无法接受。
于是想把黑色白色分开记录下来,然后两遍for,发现复杂度不变...
从黑色开始搜,如果要记忆化的话,貌似很麻烦,但是我们可以从白色的开始搜,然后开一个数组记录结果,BFS的时候更新结果数组,如果无法更新就不用再搜这个点了,因为这个点是从别处搜过来的,如果没有更小的距离,那就不用再往下搜。
代码:
/* * Author: illuz <iilluzen[at]gmail.com> * File: 206.cpp * Create Date: 2014-07-25 23:58:52 * Descripton: */ #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int N = 200; const int INF = 0x7fffffff; const int dx[] = {0, 0, 1, -1}; const int dy[] = {1, -1, 0, 0}; struct Triple { int x; int y; int rank; }; char g[N][N]; int t, n, m, res[N][N]; void bfs(int x, int y) { queue<Triple> q; q.push((Triple){x, y, 0}); while (!q.empty()) { int x = q.front().x, y = q.front().y, r = q.front().rank + 1; q.pop(); for (int i = 0; i < 4; i++) { int tx = x + dx[i], ty = y + dy[i]; if (g[tx][ty] == '0' && res[tx][ty] > r) { res[tx][ty] = r; q.push((Triple){tx, ty, r}); } } } } int main() { scanf("%d", &t); while (t--) { memset(g, 0, sizeof(g)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%s", g[i] + 1); for (int j = 1; j <= m; j++) { if (g[i][j] == '0') { res[i][j] = INF; } else { res[i][j] = 0; } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (g[i][j] == '1') { bfs(i, j); } } } for (int i = 1; i <= n; i++) { for (int j = 1; j < m; j++) { printf("%d ", res[i][j]); } printf("%d\n", res[i][m]); } } return 0; }