算法竞赛入门经典 第二版 习题4-1 象棋 Xiangqi uva1589

本文分享了解决UVA-1589问题的心得,通过使用结构体存储棋子位置并遍历判断吃子情况,有效避免了超时问题。文章详细介绍了如何判断不同棋子对“将”的威胁,并特别提到了输入格式的陷阱。

题目:https://vjudge.net/problem/UVA-1589

卡了我一个周,WA到想哭,象棋盘放在卧室一个周没收起来(┬_┬)

思路:将死,也就是说将向上下左右移动(如果可能的话)均仍被将军。
我自然的想到了建一个二维数组模拟棋盘,分别表示某行某列的棋子,然后将将上下左右移动(如果可能的话)后分别判断是否会被车马炮包括帅吃了。然而。。。迷之超时。。。3秒的运行时间竟然能超了。。。
一番调整之后仍旧超时,无奈重写,换了个想法,用结构体存储棋子的位置,判断吃子时直接遍历判断棋子即可,这比遍历棋盘循环次数少得多。

具体的判断方法:
车/帅:本题中帅与车的性质相同,若有车/帅与将之间在同一行或同一列且中间没有棋子阻隔,则将被吃。
炮:若有车/帅与将之间在同一行或同一列且中间有一个棋子,则将被吃。
马:将周围有8个被马吃的可能位点,若这些位置上有马且不蹩马腿,则将被吃。

注:(1)将可以吃掉相邻的棋子,注意处理,遍历时若有棋子与将移动后的位置相同,continue即可。
(2)输入格式问题:这题测试数据怕是有问题,这问题坑的我怀疑人生。
2 1 4
G 10 5
R 6 4
读取棋子的种类时我原本用的是scanf(“%*c%c”, &ch);
那个%*c吃的是回车符,我能用到的所有测试工具都能正常输入正常输出,然而OJ就是告诉我WA。
开始学了点c++之后改用cin >> ch;
然后就AC了这里写图片描述

代码:c风格的c++

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef struct
{
    int x,y;
} chess;
int R,H,C;
chess g,r[10],h[10],c[10];
//棋子读入
void getchess()
{
    char ch;
//    scanf("%*c%c", &ch);
    cin >> ch;//必须cin读入(原因不明)
    switch(ch)
    {
        case 'R': scanf("%d%d", &r[R].x, &r[R].y); R++; break;
        case 'G': scanf("%d%d", &r[R].x, &r[R].y); R++; break;
        case 'H': scanf("%d%d", &h[H].x, &h[H].y); H++; break;
        case 'C': scanf("%d%d", &c[C].x, &c[C].y); C++; break;
    }
}
//判断是否有棋子在此位置,用于判断蹩马腿的棋子
int loca_search(int a, int b)
{
    int i;
    for(i=0;i<R;i++)
    {
        if(r[i].x==a&&r[i].y==b)
        {
            return 1;
        }
    }
    for(i=0;i<H;i++)
    {
        if(h[i].x==a&&h[i].y==b)
        {
            return 1;
        }
    }
    for(i=0;i<C;i++)
    {
        if(c[i].x==a&&c[i].y==b)
        {
            return 1;
        }
    }
    return 0;
}
//判断某列有几个棋子在minn行与maxx行之间,用于车帅炮的判断
int y_search(int b, int minn, int maxx)
{
    int i,cot=0;
    for(i=0;i<R;i++)
    {
        if(r[i].y==b&&r[i].x>minn&&r[i].x<maxx)
        {
            cot++;
        }
    }
    for(i=0;i<H;i++)
    {
        if(h[i].y==b&&h[i].x>minn&&h[i].x<maxx)
        {
            cot++;
        }
    }
    for(i=0;i<C;i++)
    {
        if(c[i].y==b&&c[i].x>minn&&c[i].x<maxx)
        {
            cot++;
        }
    }
    return cot;
}
//判断某行有几个棋子在minn列与maxx列之间,用于车帅炮的判断
int x_search(int a, int minn, int maxx)
{
    int i,cot=0;
    for(i=0;i<R;i++)
    {
        if(r[i].x==a&&r[i].y>minn&&r[i].y<maxx)
        {
            cot++;
        }
    }
    for(i=0;i<H;i++)
    {
        if(h[i].x==a&&h[i].y>minn&&h[i].y<maxx)
        {
            cot++;
        }
    }
    for(i=0;i<C;i++)
    {
        if(c[i].x==a&&c[i].y>minn&&c[i].y<maxx)
        {
            cot++;
        }
    }
    return cot;
}
//对马判断
int horse(int a, int b)
{
    int i;
    for(i=0;i<H;i++)
    {
        if(a-2>=1)
        {
            if( (h[i].x==a-2&&h[i].y==b-1&&!loca_search(a-1,b-1)) || (h[i].x==a-2&&h[i].y==b+1&&!loca_search(a-1,b+1)) )
            {
                return 1;
            }
        }
        if(a-1>=1)
        {
            if( (h[i].x==a-1&&h[i].y==b-2&&!loca_search(a-1,b-1)) || (h[i].x==a-1&&h[i].y==b+2&&!loca_search(a-1,b+1)) )
            {
                return 1;
            }
        }
        if( (h[i].x==a+1&&h[i].y==b-2&&!loca_search(a+1,b-1)) || (h[i].x==a+1&&h[i].y==b+2&&!loca_search(a+1,b+1)) )
        {
            return 1;
        }
        if( (h[i].x==a+2&&h[i].y==b-1&&!loca_search(a+1,b-1)) || (h[i].x==a+2&&h[i].y==b+1&&!loca_search(a+1,b+1)) )
        {
            return 1;
        }
    }
    return 0;
}
//对炮判断
int cannon(int a, int b)
{
    int i,minn,maxx;
    for(i=0;i<C;i++)
    {
        if(c[i].x==a&&c[i].y==b)
            continue;
        if(c[i].x==a)
        {
            minn = c[i].y<b?c[i].y:b;
            maxx = c[i].y>b?c[i].y:b;
            if(x_search(a,minn,maxx)==1)
            {
                return 1;
            }
        }
        if(c[i].y==b)
        {
            minn = c[i].x<a?c[i].x:a;
            maxx = c[i].x>a?c[i].x:a;
            if(y_search(b,minn,maxx)==1)
            {
                return 1;
            }
        }
    }
    return 0;
}
//对车帅判断
int chariot(int a, int b)
{
    int i,minn,maxx;
    for(i=0;i<R;i++)
    {
        if(r[i].x==a&&r[i].y==b)
            continue;
        if(r[i].x==a)
        {
            minn = r[i].y<b?r[i].y:b;
            maxx = r[i].y>b?r[i].y:b;
            if(x_search(a,minn,maxx)==0)
            {
                return 1;
            }
        }
        if(r[i].y==b)
        {
            minn = r[i].x<a?r[i].x:a;
            maxx = r[i].x>a?r[i].x:a;
            if(y_search(b,minn,maxx)==0)
            {
                return 1;
            }
        }
    }
    return 0;
}
//判断将位于a行b列是是否被吃
int judge(int a, int b)
{
    if(chariot(a,b))
    {
        return 1;
    }
    if(cannon(a,b))
    {
        return 1;
    }
    if(horse(a,b))
    {
        return 1;
    }
    return 0;
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n,t;
    while(scanf("%d%d%d", &n, &g.x, &g.y))
    {
        if(n==0)
        {
            break;
        }
        R = 0;
        H = 0;
        C = 0;
        memset(r,0,sizeof(r));
        memset(h,0,sizeof(h));
        memset(c,0,sizeof(c));
        while(n--)
        {
            getchess();
        }
        t = 1;
        if(g.y!=4)
        {
            t = judge(g.x,g.y-1);
        }
        if(g.y!=6&&t==1)
        {
            t = judge(g.x,g.y+1);
        }
        if(g.x!=1&&t==1)
        {
            t = judge(g.x-1,g.y);
        }
        if(g.x!=3&&t==1)
        {
            t = judge(g.x+1,g.y);
        }
        if(t==0)
        {
            printf("NO\n");
        }
        else
        {
            printf("YES\n");
        }
    }
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值