顽皮恶魔「掘金日新计划 · 12 月更文挑战」

80 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情

顽皮恶魔

链接:ac.nowcoder.com/acm/problem…
来源:牛客网

题目描述

浮云阴,骤雨倾,顽皮恶魔镰刀显。

你的庄园是一块 n×m 的草坪。

现在有一些格子是普通植物 P,有一些格子是萝卜保护伞 *,有一些格子是僵尸 Z。(已经在格子上的僵尸不会吃掉植物或移动)

tip:萝卜保护伞可以保护周围 3×33\times33×3 的植物,即一个位于位置 (x,y)(x,y)(x,y) 的萝卜保护伞可以保护位于 (x±1,y),(x,y±1),(x±1,y±1) 以及自身九个格子上的植物。

现在你想知道,对于这样一块给定的草坪,假设有无穷多个飞贼,能够偷走最多数量的植物是多少。

输入描述:

全文第一行输入一个正整数 T(1≤T≤105),表示数据组数。

每组数据第一行输入两个正整数 n,m(1≤n,m≤103),表示草坪的长和宽。

接下来输入一个 n×m 的字符矩阵表示草坪的大小,字符矩阵中仅包含 Z、P、 * 三种字符。

数据保证 ∑n×m≤2×106

输出描述:

每行输出一个整数表示最多被偷走的植物数量。

示例1

输入

1
5 5
ZPZPZ
P*PZP
ZPZPZ
PZPZP
ZP*PZ

输出

5

说明

分别位于 (2,2) 和 (5,3) 上的保护伞可以保护周围的植物,最后能被偷走的植物如下图所示:(# 表示即将被偷走,∗ 表示保护伞,P 表示被保护)

思路

其实这个题简单来说,就是要找没有保护伞的植物,直接暴力搜索,如果找到普通植物就遍历他的身边有没有保护伞,这里我加了一个处理,不在搜索的时候就计数,搜索的时候如果遇到了保护伞,就把他能保护得范围都变成僵尸,最后直接重新遍历找P的个数就行。

代码

#include<bits/stdc++.h>
using namespace std;
char a[10010][10010];
void fun()
{
    int n,m;
    cin>>n>>m;
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
        //if(a[i][j]=='P'){ans++;}
        }
    //cout<<ans<<endl;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            //if(a[i][j]=='P'){ans++;}
            if(a[i][j]=='*')
            {
                if(a[i-1][j-1]!='*') a[i-1][j-1]='Z';
                if(a[i-1][j]!='*') a[i-1][j]='Z';
                if(a[i-1][j+1]!='*') a[i-1][j+1]='Z';
                if(a[i][j-1]!='*') a[i][j-1]='Z';
                if(a[i][j+1]!='*') a[i][j+1]='Z';
                if(a[i+1][j-1]!='*') a[i+1][j-1]='Z';
                if(a[i+1][j]!='*') a[i+1][j]='Z';
                if(a[i+1][j+1]!='*') a[i+1][j+1]='Z';
             }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]=='P') ans++;
            }
        cout<<ans<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        fun();
    }
    return 0;
}