这题考察我们的大脑体力,非常难调,我花了3.5小时,要是在区域赛里做着题,我碰都不碰,没有大样例非常难受。
分析如下:
- 中国象棋,见百度百科
- 就是考虑当前情况下将军是不是已经给将死了
考虑:
- 飞将
- 将军吃掉了红色棋子的情况
- 马脚问题
- 将军只能在一定的区域内移动
- 注意边界情况
- 善用工具来debug,我用了udebug,里面有一个大样例,cmd我是可以看到输入的,但吞了我一部分输出,搞得我虚空调试,我一个一个对照才发现我代码早就是对的了,这也是教训
// AC one more times
////////////////////////////////////////INCLUDE//////////////////////////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include<string>
#include<string.h>
#include <cstring>
#include <complex>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <list>
#include <bitset>
#include <assert.h>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <random>
#include <iterator>
#include <time.h>
using namespace std;
/////////////////////////////////////////DEFINE//////////////////////////////////////////
#define fi first
#define se second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define inf64 0x3f3f3f3f3f3f3f3f
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<long long,long long> PLL;
////////////////////////////////////////CONST////////////////////////////////////////////
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 6;
const double eps = 1e-8;
const long long mod = 1000000;
///////////////////////////////////////FUNCTION//////////////////////////////////////////
template<typename T>
void init(T q[], int n, T val){ for (int i = 0; i <= n; i++) q[i] = val; }
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
bool cmp(int c, int d) { return c > d; }
int n,bi,bj;
int dx[]={0,0,1,-1}; // 普通的四个方向位移
int dy[]={1,-1,0,0};
int hx[]={0, -2,-2, -1,1, 2,2, 1,-1 }; //马的位移量
int hy[]={0, -1, 1, 2,2, 1,-1, -2,-2 };
char op[15][15]; //最开始的棋盘
char ma [15][15]; //将军位移了的棋盘
int ans[15][15]; //将军位移的情况下,哪些地方可以吃的棋盘 1做标记
bool check1() //检查黑将军能不能吃掉帅
{
for(int i=bi+1;i<=10;i++)
{
if(op[i][bj]==' ') continue;
else if(op[i][bj]=='G') return true;
else break;
}
return false;
}
bool check_address(int x,int y) //检查将军的位移是否合法
{
if(x>=1&&x<=3&&y>=4&&y<=6) return true;
else return false;
}
bool check_bound(int x,int y) //检查棋子是不是在棋盘内,位移是否合法
{
if(x>=1&&x<=10&&y>=1&&y<=9) return true;
else return false;
}
// 车和帅可以合并,两者有共性
void che(int x,int y) //车四个方向一直打,直到遇到棋子和边界
{
for(int i=x+1;i<=10;i++)
{
if(ma[i][y]==' ') ans[i][y]=1;
else break;
}
for(int i=x-1;i>=1;i--)
{
if(ma[i][y]==' ') ans[i][y]=1;
else break;
}
for(int j=y+1;j<=9;j++)
{
if(ma[x][j]==' ') ans[x][j]=1;
else break;
}
for(int j=y-1;j>=1;j--)
{
if(ma[x][j]==' ') ans[x][j]=1;
else break;
}
}
void pao(int x,int y) // 炮四个方向分别找到第一个棋子,然后一直打,知道遇到棋子和边界停下来
{
for(int i=x+1;i<=10;i++)
if(ma[i][y]!=' ')
{
for(int j=i+1;j<=10;j++)
{
if(ma[j][y]!=' ') break; // 打不了了,不打了
ans[j][y]=1;
}
break;
}
for(int i=x-1;i>=1;i--)
if(ma[i][y]!=' ')
{
for(int j=i-1;j>=1;j--)
{
if(ma[j][y]!=' ') break; // 打不了了,不打了
ans[j][y]=1;
}
break;
}
for(int j=y+1;j<=9;j++)
if(ma[x][j]!=' ')
{
for(int i=j+1;i<=9;i++)
{
if(ma[x][i]!=' ') break; // 打不了了,不打了
ans[x][i]=1;
}
break;
}
for(int j=y-1;j>=1;j--)
if(ma[x][j]!=' ')
{
for(int i=j-1;i>=1;i--)
{
if(ma[x][i]!=' ') break; // 打不了了,不打了
ans[x][i]=1;
}
break;
}
}
void maa(int x,int y,int k) // 马这里算了四个情况来考虑马给卡脚的情况,我看也向是四个方向
{
// k代表方向
if(k==1)
{
if(ma[x-1][y]==' '&&check_bound(x-1,y)) //检查是是否卡马脚,和位移是否合法
for(int m=1;m<=2;m++)
{
int tx=x+hx[m],ty=y+hy[m];
if(check_bound(tx,ty)==true&&ma[tx][ty]==' ')
ans[tx][ty]=1;
}
}
else if(k==2)
{
if(ma[x][y+1]==' '&&check_bound(x,y+1)) //检查是是否卡马脚,和位移是否合法
{
for(int m=3;m<=4;m++)
{
int tx=x+hx[m],ty=y+hy[m];
if(check_bound(tx,ty)==true&&ma[tx][ty]==' ')
ans[tx][ty]=1;
}
}
}
else if(k==3)
{
if(ma[x+1][y]==' '&&check_bound(x+1,y)) //检查是是否卡马脚,和位移是否合法
{
for(int m=5;m<=6;m++)
{
int tx=x+hx[m],ty=y+hy[m];
if(check_bound(tx,ty)==true&&ma[tx][ty]==' ')
ans[tx][ty]=1;
}
}
}
else if(k==4)
{
if(ma[x][y-1]==' '&&check_bound(x,y-1)) //检查是是否卡马脚,和位移是否合法
{
for(int m=7;m<=8;m++)
{
int tx=x+hx[m],ty=y+hy[m];
if(check_bound(tx,ty)==true&&ma[tx][ty]==' ')
ans[tx][ty]=1;
}
}
}
}
void solve()
{
memset(op,' ',sizeof op);
//存点 最开始的棋盘
for(int i=1;i<=n;i++)
{
char c; int x,y; cin>>c>>x>>y;
op[x][y]=c;
}
// 飞将的判断
bool check = false ;
check=check1();
if(check==true)
{
cout<<"NO"<<endl;
return;
}
int sum1=0;
//枚举将军的能到达的点
for(int m=0;m<=3;m++)
{
int x=bi+dx[m],y=bj+dy[m];
if(check_address(x,y)==false) continue; //将位移的合法性
sum1++;
//复制一份地图, 在将位移可能吃掉红子
memset(ma,' ',sizeof ma);
for(int i=1;i<=10;i++)
for(int j=1;j<=9;j++)
if(i==x&&j==y) continue;
else ma[i][j]=op[i][j];
//枚举红方的棋子,哪些地方会被吃
//ans 来记录
memset(ans,0,sizeof ans); //将“将军位移的情况下,哪些地方可以吃的棋盘 1做标记”的数组全计为0
for(int i=1;i<=10;i++)
{
for(int j=1;j<=9;j++)
{
if(ma[i][j]=='R')
che(i,j); //车
else if(ma[i][j]=='C')
pao(i,j); //炮
else if(ma[i][j]=='H')
{
for(int k=1;k<=4;k++)
{
maa(i,j,k); //马
}
}
else if(ma[i][j]=='G')
{
che(i,j); //帅
}
}
}
//输出可以吃的地图检查
/*
for(int i=1;i<=10;i++)
{
for(int j=1;j<=9;j++)
{
cout<<ans[i][j];
}
cout<<endl;
}
cout<<endl;
cout<<endl;
cout<<m<<" "<<sum1<<endl;
*/
if(ans[x][y]==1)
sum1--;
}
//sum1 代表将军可以走到的点的数量,当走到的点会给吃就--,当sum=0说明无路可走
if(sum1==0)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return;
}
int main()
{
std::ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
while(cin>>n>>bi>>bj)
{
if(n==0&&bi==0&&bj==0) return 0;
solve();
}
return 0;
}
本文来自博客园,作者:magicat,转载请注明原文链接:https://www.cnblogs.com/magicat/p/16301119.html
浙公网安备 33010602011771号