题意:n*m的方块~1000 然后本来是每块有可能有一个‘L’标记,并且每一块可以算出来一个值:由它周围有效的9(包括自己)块推出来,如果它有就额外+3,然后9个中有几个L就+几,最大12.现在,给出一个有效状态的转化之后的方块,求出初始状态。
题解:显然从最左上的开始试着推,左上可以确定,然后(1,2)怎么搞?发现(1,1)(2,1)(1,2)(2,2)的总数因为(1,1)已经知道了,只剩(1,3)(2,3)两块了,又能够无视它定出来(1,2),然后想(1,3),虽然(1,3)还是能够定出来,但是(1,4)就不好弄了,关键是(2,x)的都不知道,重点来了:我们不妨把(2,x)同时确定下来,这样两行一块推,(2,1)好定,(2,2)由于4个定了3个,这个发现也很重要,可以定(2,2),之后发现已经行了,因为之后的(1,3)可以定了,那么(2,3)呢?因为(1,2)周围定了5个,所以减一下就好了。之后一直推完第一行,然后第三行,先把第二行信息弄掉就和刚才的一样了。
重点:首先试着去推,发现(1,4)不行去想(2,x),然后很重到的是(2,2)的减法,搞出来了,然后(1,3)之后(2,3)同样的减法。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = 1e3 +100;
int m, n;
int a[maxn][maxn], ans[maxn][maxn];
void solve()
{
for(int i = 1;i <= m;i += 2)//周围的ans都变成0,不用特殊化处理。
{
for(int j = 1;j <= n;j++)//先把上一层减掉。
{
a[i][j] = a[i][j] - ans[i-1][j-1]-ans[i-1][j]-ans[i-1][j+1];
}
if(a[i][1] >= 4)//前四个是特殊化的,具体怎么弄关键写的时候就清楚了
{
ans[i][1] = 1;
a[i][1] -= 3;
}
if(a[i][2]-a[i][1] >= 3)
{
ans[i][2] = 1;
}
if(a[i+1][1]-a[i][1] >= 3)
{
ans[i+1][1] = 1;
}
ans[i+1][2] = a[i][1]-ans[i][1]-ans[i][2]-ans[i+1][1];
for(int j = 3;j <= n;j++)//开始两个两个推
{
if(a[i][j]-ans[i][j-1]-ans[i+1][j-1]>=4)
{
ans[i][j] = 1;
}
ans[i+1][j] = a[i][j-1]-4*ans[i][j-1]-ans[i][j-2]-ans[i][j]-ans[i+1][j-1]-ans[i+1][j-2];
}
}
REP_D(i, 1, m)
{
REP_D(j, 1, n)
{
if(ans[i][j])
{
printf("L");
}
else
{
printf("-");
}
}
printf("\n");
}
}
int main()
{
freopen("7Gin.txt", "r", stdin);
//freopen("7Gout.txt", "w", stdout);
int ncase;
scanf("%d", &ncase);
while(ncase--)
{
scanf("%d%d", &m, &n);
REP_D(i, 1, m)
{
REP_D(j, 1, n)
{
scanf("%d", &a[i][j]);
}
}
CLR(ans);
solve();
}
return 0;
}