洛谷:P6194 [EER1] 苏联人

文章描述了一个编程问题,要求在给定的国际象棋棋盘上确定白色国王的安全位置,即不能被黑色战车或主教直接攻击。解题者给出了一个C++程序示例,展示了如何考虑棋子的移动范围和阻碍来找出这些安全格子。
摘要由CSDN通过智能技术生成

时间限制1.00s         内存限制125.00MB          难易度:普及−

【题目背景】

题目名称是吸引你点进来的。

这是一道正常的题,和苏联没有任何关系。

【题目描述】

你在打 EE Round 1,发现第一题非常无聊。于是你不打了,去下国际象棋了。

结果你发现,由于神秘力量的影响,你的棋子只剩下若干黑色的战车,若干黑色的主教和一只白色的国王了。

由于你很无聊,所以你把一些黑色棋子放在了 8×8 的棋盘上。

由于你很无聊,所以你想知道,国王放在哪些格子是安全的。换句话说,有哪些格子不会被战车和主教攻击到。当然,国王不能放在已经有棋子的地方

为了防止你无聊透顶而不知道国际象棋的规则,这里给出以下提示(如果你知道规则那么可以跳过):

国际象棋中,战车可以横向、竖向移动,且格数不受限制。但不能越过其他棋子

如图,黄色的格子为战车能走到(攻击到)的格子。

国际象棋中,主教可以斜向移动,且格数不受限制。但不能越过其他棋子

如图,黄色的格子为主教能走到(攻击到)的格子。

简单来说,如果当前位置到目标位置的直线上存在其他棋子,则可以称为“越过了其他棋子”。

如果目标位置是对方的棋子,那么移动到目标位置后,对方的棋子会被吃掉。

更进一步地,你要找的所有位置,必须满足没有黑色棋子能一步走到。


如果你还是没有读懂,可以结合样例进行理解。

【输入格式】

共 8 行,每行 8 个字符,表示棋盘的状态。

其中 . 表示空位,R 表示战车,B 表示主教。

【输出格式】

共 8 行,每行 8 个字符。若一个格子是可以放国王的,则输出 1,否则输出 0

【输入输出样例】

输入 #1

........
........
........
..B..R..
........
........
........
........

输出 #1

11111011
01110011
10101011
11000000
10101011
01110011
11111011
11111001

【说明/提示】

对于 100% 的数据,保证只会出现 .RB 三种字符。

本题共有 4 个子任务,每个子任务的限制如下:

子任务 1(10 分):保证只会出现 .

子任务 2(20 分):保证只会出现一个 R 或一个 B(不同时出现)。

子任务 3(30 分):保证只有一个 .

子任务 4(40 分):没有特殊限制。

【算法分析】

都有谁是因为题目才看这道题的?我点进去才发现是一道关于国象的模拟题,这道题目的作者真是大大滴狡猾。

这道题是一道简单的模拟题,但有坑,我先依据题目得出

#include <bits/stdc++.h>
using namespace std;
char chess[8][8];
int ans[8][8];
int main()
{
    for(int i=0;i<8;i++)
		for(int j=0;j<8;j++)
			cin>>chess[i][j];
    for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++)
        {
            if(chess[i][j]=='R')
            {
                ans[i][j]=1;
                for(int k=i-1;k>=0;k--) ans[k][j]=1;
                for(int k=i+1;k<8;k++) ans[k][j]=1;
                for(int k=j-1;k>=0;k--) ans[i][k]=1;
                for(int k=j+1;k<8;k++) ans[i][k]=1;
            }
            else if(chess[i][j]=='B')
            {
                ans[i][j]=1;
                for(int k=i-1,l=j-1;k>=0,l>=0;k--,l--) ans[k][l]=1;
                for(int k=i+1,l=j+1;k<8,l<8;k++,l++) ans[k][l]=1;
                for(int k=i-1,l=j+1;k>=0,l<8;k--,l++) ans[k][l]=1;
                for(int k=i+1,l=j-1;k<8,l>=0;k++,l--) ans[k][l]=1;
            }
        }
    }
    for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++) 
        {
            if(ans[i][j]==1) cout<<"0";
            else cout<<"1";
        }
        cout<<endl;
    }
    return 0;
}

发现RE,加大了数组后还不行。

char chess[10][10];
int ans[10][10];

 我又双叒叕研究了两年半的题目与样例和国象规则,发现我忘记了,棋子(不论车象)的攻击可能会被另一个棋子阻挡,作为Play chess两年半高玩,忘记这个,我着实有些惭愧。

chess[ ][ ]=='.' //for循环条件中加这个

【参考代码】

#include <bits/stdc++.h>
using namespace std;
char chess[10][10];
int ans[10][10];
int main()
{
    for(int i=0;i<8;i++)
		for(int j=0;j<8;j++)
			cin>>chess[i][j];
    for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++)
        {
            if(chess[i][j]=='R')//战车
            {
                ans[i][j]=1;
                for(int k=i-1;k>=0&&chess[k][j]=='.';k--) ans[k][j]=1;//上方
                for(int k=i+1;k<8&&chess[k][j]=='.';k++) ans[k][j]=1;//下方
                for(int k=j-1;k>=0&&chess[i][k]=='.';k--) ans[i][k]=1;//左边
                for(int k=j+1;k<8&&chess[i][k]=='.';k++) ans[i][k]=1;//右边
            }
            else if(chess[i][j]=='B')//主教
            {
                ans[i][j]=1;
                for(int k=i-1,l=j-1;k>=0,l>=0&&chess[k][l]=='.';k--,l--) ans[k][l]=1;//左上方
                for(int k=i+1,l=j+1;k<8,l<8&&chess[k][l]=='.';k++,l++) ans[k][l]=1;//右下方
                for(int k=i-1,l=j+1;k>=0,l<8&&chess[k][l]=='.';k--,l++) ans[k][l]=1;//右上方
                for(int k=i+1,l=j-1;k<8,l>=0&&chess[k][l]=='.';k++,l--) ans[k][l]=1;//左下方
            }
        }
    }
    for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++) 
        {
            if(ans[i][j]==1) cout<<"0";//因为ans初始为0,所以能放的地方取的是1,输出要取反。
            else cout<<"1";
        }
        cout<<endl;
    }
    return 0;
}

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值