SGU 125.Shtirlits
时间限制:0.25s
空间限制:4M
题意:
有N*N的矩阵(n<=3),对所有i,j<=n有G[i][j]<=9,定义f[i][j]为G[i][j]四周大于它的数的个数(F[i][j]<=4),
现在 给出n和F[i][j],输出一种可形的G。
Sample Input
3
1 2 1
1 2 1
1 1 0
Sample Output
1 2 3
1 4 5
1 6 7
Solution:
观察给出的F矩阵,以样例为例
1 | 2 | 1 |
1 | 2 | 1 |
1 | 1 | 0 |
首先知道
F[3][3]==0,那么G[3][3]一定是最大的,令当前填的数为K(K=N*N)
这时将F[3][3],四周的所有F[i][j]减1,变成
1 | 2 | 1 |
1 | 2 | 0 |
1 | 0 | # |
(#号代表已填)
这样重复上面的步骤,每次做完执行k--
直到发现
1 | 2 | 0 |
0 | 0 | # |
# | # | # |
这时对应的G为
* | * | * |
* | * | 7 |
6 | 8 | 9 |
(*代表还未填)
F出现两个以上接触的0,那么同时填这些接触的0为K
此时F矩阵为
0 | 1 | 0 |
# | # | # |
# | # | # |
G矩阵为
* | * | * |
5 | 5 | 7 |
6 | 8 | 9 |
最后得到G矩阵
3 | 3 | 4 |
5 | 5 | 7 |
6 | 8 | 9 |
这样就得到了一种满足要求的输出
最后总结就是,令k=n*n,对F填一个F[i][j]==0的位置为k,如果有联通的0,将这些为0的位置全部填为K,
再将填了数的位置的四周的F[i][j]减一。
如果填完所有0的位置后,G矩阵已经填完那么输出G
G没有填完的话,输出“No Solution”;
参考代码:
#include <iostream> #include <queue> #include <cstring> using namespace std; struct node { int x, y; } p; int dirx[4] = {0, 0, -1, 1}, diry[4] = {1, -1, 0, 0}; int g[5][5], f[5][5], pd[5][5]; int n, t, k; queue<node> ql; void BFS (int x, int y, int k) { node p; for (int i = 0; i <= 3; i++) { p.x = x + dirx[i], p.y = y + diry[i]; if (f[p.x][p.y] == 0) { g[p.x][p.y] = k, t++; f[p.x][p.y] = -1, pd[p.x][p.y] = 1; BFS (p.x, p.y, k); } else if (f[p.x][p.y] > 0) if ( (--f[p.x][p.y]) == 0) ql.push (p); } } int main() { cin >> n; memset (f, -1, sizeof f); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { cin >> f[i][j]; if (f[i][j] == 0) { p.x = i, p.y = j; ql.push (p); } } k = n * n; for (node p; !ql.empty(); ql.pop(), k--) { p = ql.front(); if (pd[p.x][p.y]) continue; pd[p.x][p.y] = 1, g[p.x][p.y] = k, f[p.x][p.y] = -1, t++; BFS (p.x , p.y, k); } if (t != n * n) cout << "NO SOLUTION"; else for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) cout << g[i][j] << ' '; cout << endl; } return 0; }