UVA - 1589 Xiangqi 【递归】

本文探讨了一道关于象棋残局的算法题,重点在于判断红方是否已将黑方将死。通过分析棋子位置和象棋规则,如“别马脚”和将帅不能照面,设计了一个解决方案,利用C++实现并分享了AC代码。

题目传送门

题目大意:考虑一个象棋残局,其中红方有n(2<=n<=7)个棋子,黑方只有一个将。红方除了有一个帅(G)之外还有3种可能的棋子:车(R),马(H),炮(C),并且还需要考虑“别马脚”与将和帅不能照面(将、帅如果同在一条线上,中间又不隔着任何棋子的情况下,走子的一方获胜)的规则。输入所有棋子的位置,保证局面合法并且红方已经将军。你的任务是判断红方是否已经把黑方将死。

解题思路:

  1. 将和帅是否在同一条线上,若是则红方败,输出NO,否则输出YES
  2. 判断黑方是否有位置可以走而不被将死,若不存在则表明黑方已被将死,输出YES,否则输出NO

(对不懂象棋规则的人来说削微有点儿坑,我就是被坑了,还有就是输入输出本来我用的scanf和printf,一直wa,改为cin和cout以后就对了(╥╯^╰╥))

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define mc(a,b) memcpy(a,b,sizeof(b))
#define inf 0x3f3f3f
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
typedef long long ll;
typedef unsigned long long ULL;
const int mod=1e9+7;
const int N=1e5+7;
struct node
{
    int x,y;
    char ch;
} a[110];
int n,x,y;
char arr[15][15];
int dx[]= {0,0,-1,1};
int dy[]= {-1,1,0,0};
int dxx[]= {-1,-2,1,2,-2,-1,1,2};
int dyy[]= {-2,-1,2,1,1,2,-2,-1};
int dxxx[]= {-1,-1,1,1,-1,-1,1,1};
int dyyy[]= {-1,-1,1,1,1,1,-1,-1};
bool judge(int a,int b)
{
    int r,c;
    r=a;
    c=b;
    while(r>=1)
    {
        if(arr[r][c]=='R') return false;
        else if(arr[r][c]=='H'||arr[r][c]=='C') break;
        r--;
    }
    r=a;
    while(r<=10)
    {
        if(arr[r][c]=='R'||arr[r][c]=='G') return false;
        else if(arr[r][c]=='H'||arr[r][c]=='C') break;
        r++;
    }
    r=a;
    while(c>=1)
    {
        if(arr[r][c]=='R') return false;
        else if(arr[r][c]=='H'||arr[r][c]=='C') break;
        c--;
    }
    c=b;
    while(c<=10)
    {
        if(arr[r][c]=='R') return false;
        else if(arr[r][c]=='H'||arr[r][c]=='C') break;
        c++;
    }
    c=b;
    for(int i=0; i<8; i++)
    {
        int xx=r+dxx[i];
        int yy=c+dyy[i];
        int xxx=r+dxxx[i];
        int yyy=c+dyyy[i];
        if(xx>=1&&x<=10&&yy>=1&&yy<=9)
            if(arr[xx][yy]=='H'&&arr[xxx][yyy]=='0') return false;
    }
    int cnt=0;
    while(r>=1)
    {
        if(arr[r][c]!='0') cnt++;
        if(cnt==2&&arr[r][c]=='C') return false;
        if(cnt>=2) break;
        r--;
    }
    r=a;
    cnt=0;
    while(r<=10)
    {
        if(arr[r][c]!='0') cnt++;
        if(cnt==2&&arr[r][c]=='C') return false;
        if(cnt>=2) break;
        r++;
    }
    r=a;
    cnt=0;
    while(c>=1)
    {
        if(arr[r][c]!='0') cnt++;
        if(cnt==2&&arr[r][c]=='C') return false;
        if(cnt>=2) break;
        c--;
    }
    c=b;
    cnt=0;
    while(c<=10)
    {
        if(arr[r][c]!='0') cnt++;
        if(cnt==2&&arr[r][c]=='C') return false;
        if(cnt>=2) break;
        c++;
    }
    return true;
}
int main()
{
//    fin;
//    fout;
    while(cin>>n>>x>>y)
    {
        for(int i=1; i<=10; i++)
            for(int j=1; j<=9; j++)
                arr[i][j]='0';
        if(n==0&&x==0&&y==0) break;
        getchar();
        for(int i=0; i<n; i++)
        {
            cin>>a[i].ch>>a[i].x>>a[i].y;
            arr[a[i].x][a[i].y]=a[i].ch;
            getchar();
        }
        int i=0;
        int r=x,c=y;
        int f=0;
        while(r<=10)
        {
            if(arr[r][c]=='G') {f=1; break;}
            else if(arr[r][c]!='0') break;
            r++;
        }
        for(i=0; i<4; i++)
        {
            int xx=x+dx[i];
            int yy=y+dy[i];
            if(xx>=1&&xx<=3&&yy>=4&&yy<=6)
            {
                char temp=arr[xx][yy];
                arr[xx][yy]='0';
                if(judge(xx,yy)) break;
                arr[xx][yy]=temp;
            }
        }
        if(i==4&&f==0) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值