题解:B4183 [中山市赛 2024] 象战

· · 题解

题解:B4183 [中山市赛 2024] 象战

题目传送门

更好的阅读体验

题目分析

一道纯模拟,可以培养全面思考问题的能力,适合新手做。

观察 "象" 所在的位置,发现如果令 "象" 的坐标为 (x,y),那么 (x+1,y+1)(x+1,y-1)(x-1,y+1)(x-1,y-1) 都会是 "象" 可以攻击到的。

所以,如果 (x,y)#,且 (x+1,y+1)(x+1,y-1)(x-1,y+1)(x-1,y-1) 也都是 #,那么这个点就是 "象" 所在的位置。

代码实现

代码:

//洛谷 B4183 [中山市赛 2024] 象战
#include<bits/stdc++.h>
using namespace std;
//#define int long long//
#define endl '\n'
#define emdl '\n'
typedef long long ll;
const int MAXN=8+5;
int n=8;
char mp[MAXN][MAXN]; 
bool pd(int x,int y){
    if(mp[x][y]=='#'){
        if(mp[x+1][y+1]=='#'){
            if(mp[x+1][y-1]=='#'){
                if(mp[x-1][y+1]=='#'){
                    if(mp[x-1][y-1]=='#'){
                        return 1;
                    }
                    else return 0;
                }
                else return 0;
            }
            else return 0;
        }
        else return 0;
    }
    else return 0;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>mp[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(pd(i,j)){
                cout<<i<<" "<<j<<endl;
                return 0;
            }
        }
    }
    return 0;
}

如果你是这么写的话,恭喜你,喜提 70 分。

为什么会这样呢?

仔细分析一下题意,我们会发现我们漏了一种情况没讨论。

什么情况呢?没错!是 "象" 所在的点在棋盘边缘的情况。

想到了情况,我们该怎么实现呢?

我想到了两种解决方案:

  1. 一种比较笨的方法。具体是枚举 "象" 在边缘的所有可能,并特殊处理。

  2. 比较聪明的办法。我们发现,无论 "象" 在边缘的哪里,实际上只用判断两种在棋盘内部的可能,另外两种可能会在棋盘外部,所以不妨初始化每个棋盘外部的点为 #,然后特判一下棋盘的四个顶点即可。

容易证明,上述方法都是对的。

真-代码实现

这里采用方案 2。

和上面代码不同的地方已近用注释展示了。

变量、数组、函数所表示的含义皆与上面的代码相同。

代码:

//洛谷 B4183 [中山市赛 2024] 象战
#include<bits/stdc++.h>
using namespace std;
//#define int long long//
#define endl '\n'
#define emdl '\n'
typedef long long ll;
const int MAXN=8+5;
int n=8;
char mp[MAXN][MAXN];
bool pd(int x,int y){
    if(mp[x][y]=='#'){
        if(mp[x+1][y+1]=='#'){
            if(mp[x+1][y-1]=='#'){
                if(mp[x-1][y+1]=='#'){
                    if(mp[x-1][y-1]=='#'){
                        return 1;
                    }
                    else return 0;
                }
                else return 0;
            }
            else return 0;
        }
        else return 0;
    }
    else return 0;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //32 至 36 行有增改 
    for(int i=0;i<=n+1;i++){
        for(int j=0;j<=n+1;j++){
            mp[i][j]='#';
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>mp[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            //45 至 48 行有增改 
            if(i==1&&j==1) continue;
            if(i==1&&j==n) continue;
            if(i==n&&j==1) continue;
            if(i==n&&j==n) continue;
            //这里一定要 continue
            //题目保证了 "象" 不会在这里,无需担心正确性
            if(pd(i,j)){
                cout<<i<<" "<<j<<endl;
                return 0;
            }
        }
    }
    return 0;
}