题意:
给定N,M≤1000的数字雷图,试恢复原来的雷图,输入保证答案唯一
有雷的格子显示3+9宫格雷数,无雷的格子显示0+9宫格雷数
分析:
1 2 3 4 5 6 7 8 9 我们以3∗3的数字雷图为例,如上图
- 记ai:=显示数,ansi:=有雷与否
观察1号格子,它掌控4个格子,若无雷显示[0,3],有雷则显示[4,8],显然我们可以得到ans1=a1>3
确定有雷之后我们把多余的3减去,也就是 if(ansi) ai−=3
接下来我们观察4号格子,我们可以发现一个等式a4−a1=ans7+ans8<=2(多余的3已经减去了)
那么显然如果a4−a1>2的话这个格子一定有雷了- 接下来我们观察2,5两个格子,我们在a2的基础上减掉前一列也就是ans1和ans4的影响
我们发现,此时问题跟刚才一样了,同样的4个格子,ans2=a2>3
对于5号格子显然可以得到ans5=a1−ans1−ans2−ans4- 接下来我们只要重复这个过程就可以得到所有格子的答案了
- 注意最后一行的时候,消除前一列的影响的时候,仅仅只有一个格子
- 除了消去前一列的影响,每次计算还要消去前一行的影响
这种题debug还是自己写数据生成器吧
代码:
//
// Created by TaoSama on 2015-12-12
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m, a[N][N];
bool ans[N][N];
void setMine(int i, int j) {
ans[i][j] = true;
a[i][j] -= 3;
}
void delLastColumn(int i, int j) {
a[i][j] -= ans[i][j - 1];
if(i < n) a[i][j] -= ans[i + 1][j - 1];
}
void see(int i, int j) {
printf("a[%d][%d] = %d ans: %d\n", i, j, a[i][j], ans[i][j]);
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
memset(a, 0, sizeof a);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf("%d", &a[i][j]);
memset(ans, false, sizeof ans);
for(int i = 1; i <= n; i += 2) {
for(int j = 1; j <= m; ++j) //delete last line
a[i][j] -= ans[i - 1][j - 1] + ans[i - 1][j] + ans[i - 1][j + 1];
//is mine
if(a[i][1] > 3) setMine(i, 1);
//only 2 left
if(a[i + 1][1] - a[i][1] > 2) setMine(i + 1, 1);
for(int j = 2; j <= m; ++j) {
// see(i, j);
delLastColumn(i, j);
// see(i, j);
if(a[i][j] > 3) setMine(i, j);
ans[i + 1][j] = a[i][j - 1] - ans[i][j - 1] - ans[i + 1][j - 1] - ans[i][j];
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j)
putchar("-L"[ans[i][j]]);
puts("");
}
}
return 0;
}