Landmine Cleaner

题目链接

题意: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值