象棋 UVa1589

  看到这个题目基本的想法是,将黑将能走的四个方向都遍历一遍,然后再判断判断红方能否吃掉它。如果所有可能的走向都会被将死,则黑将被将死。需要注意越界,吃子,和马被别脚的情况。附上一张自己画的一张简图可能会清楚一些:
  思路导图
下面贴一下代码,更详细的解释在代码的注释里,代码有点冗长,有能力的可以把相同的地方写成函数(比如说帅和车的判断是可以放一起的)

#include<iostream>
#include<fstream>
using namespace std;
struct qizhi
{
    char kind;
    int row;
    int column;
};

int panduan(int b_row, int b_column, int size, const qizhi*  p)   //用来判断黑将走某一步会不会被将死,如果会死返回0,不会返回1
{
    for (int i = 0; i < size; ++i)
    {
        switch (p[i].kind)
        {
        case 'G':
            if (p[i].column == b_column)
            {
                int key = 0;   //标记,
                for (int j = 0; j < size; ++j)    //如果黑将和红帅在同列,判断中间有没有其他的旗子
                {
                    if (j == i)
                        continue;
                    if (p[j].column == p[i].column&&p[j].row > b_row&&p[j].row < p[i].row)
                    {
                        key = 1;
                        break;
                    }
                }
                if (0 == key)
                    return 0;            //如果key为0,表面被将死直接返回0
            }
            break;
        case 'R':
            if (p[i].column == b_column)
            {
                int key = 0, key1;   //标记,
                p[i].row > b_row ? key1 = 1 : key1 = 0;
                for (int j = 0; j < size; ++j)    //如果黑将和车在同列,判断中间有没有其他的旗子
                {
                    if (j == i)
                        continue;
                    if (key1 == 1)
                    {
                        if (p[j].column == p[i].column&&p[j].row > b_row&&p[j].row < p[i].row)
                        {
                            key = 1;
                            break;
                        }
                    }
                    else
                    {
                        if (p[j].column == p[i].column&&p[j].row <b_row&&p[j].row > p[i].row)
                        {
                            key = 1;
                            break;
                        }
                    }

                }
                if (0 == key)
                    return 0;            //如果key为0,表明被将死直接返回0
            }
            if (p[i].row == b_row)
            {
                int key = 0, key1;   //标记,
                p[i].column > b_column ? key1 = 1 : key1 = 0;
                for (int j = 0; j < size; ++j)    //如果黑将和车在同行,判断中间有没有其他的旗子
                {
                    if (j == i)
                        continue;
                    if (key1 == 1)
                    {
                        if (p[j].row == p[i].row&&p[j].column > b_column&&p[j].column < p[i].column)
                        {
                            key = 1;
                            break;
                        }
                    }
                    else
                    {
                        if (p[j].row == p[i].row&&p[j].column < b_column&&p[j].column > p[i].column)
                        {
                            key = 1;
                            break;
                        }
                    }

                }
                if (0 == key)
                    return 0;            //如果key为0,表明被将死直接返回0
            }
            break;
        case 'C':
            if (p[i].column == b_column)
            {
                int key = 0, key1;   //标记,
                p[i].row > b_row ? key1 = 1 : key1 = 0;
                for (int j = 0; j < size; ++j)    //如果黑将和炮在同列,判断中间有多少个旗子
                {
                    if (j == i)
                        continue;
                    if (1 == key1)
                    {
                        if (p[j].column == p[i].column&&p[j].row > b_row&&p[j].row < p[i].row)
                        {
                            key += 1;
                        }
                    }
                    else
                    {
                        if (p[j].column == p[i].column&&p[j].row<b_row&&p[j].row>p[i].row)
                        {
                            key += 1;
                        }
                    }

                }
                if (1 == key)
                    return 0;            //如果key为1,表明被将死直接返回0
            }
            if (p[i].row == b_row)
            {
                int key = 0, key1;   //标记,
                p[i].column > b_column ? key1 = 1 : key1 = 0;
                for (int j = 0; j < size; ++j)    //如果黑将和炮在同行,判断中间有多少个旗子
                {
                    if (j == i)
                        continue;
                    if (1 == key1)
                    {
                        if (p[j].row == p[i].row&&p[j].column > b_column&&p[j].column < p[i].column)
                        {
                            key += 1;
                        }
                    }
                    else
                    {
                        if (p[j].row == p[i].row&&p[j].column<b_column&&p[j].column>p[i].column)
                        {
                            key += 1;
                        }
                    }
                }
                if (1 == key)
                    return 0;            //如果key为1,表明被将死直接返回0
            }
            break;
         case 'H':
            int up = 0, down = 0, left = 0, right = 0;
            for (int j = 0; j < size; ++j)    //判断向上是否会别马脚
            {
                if (j == i)
                    continue;
                if (p[j].row == p[i].row - 1 && p[j].column == p[i].column)
                {
                    up = 1;
                    break;                          //如果别马脚,就结束
                }
            }
            if (0 == up)
            {
                if (p[i].column - 1 == b_column&&p[i].row - 2 == b_row)
                    return 0;
                else if (p[i].column + 1 == b_column&&p[i].row - 2 == b_row)
                    return 0;
            }
            for (int j = 0; j < size; ++j)    //判断向左是否会别马脚
            {
                if (j == i)
                    continue;
                if (p[j].row == p[i].row && p[j].column == p[i].column - 1)
                {
                    left = 1;
                    break;                          //如果别马脚,就结束
                }
            }
            if (0 == left)
            {
                if (p[i].column - 2 == b_column&&p[i].row - 1 == b_row)
                    return 0;
                else if (p[i].column - 2 == b_column&&p[i].row + 1 == b_row)
                    return 0;
            }
            for (int j = 0; j < size; ++j)    //判断向右是否会别马脚
            {
                if (j == i)
                    continue;
                if (p[j].row == p[i].row && p[j].column == p[i].column + 1)
                {
                    right = 1;
                    break;                          //如果别马脚,就结束
                }

            }
            if (0 == right)
            {
                if (p[i].column + 2 == b_column&&p[i].row - 1 == b_row)
                    return 0;
                else if (p[i].column + 2 == b_column&&p[i].row + 1 == b_row)
                    return 0;
            }
            for (int j = 0; j < size; ++j)    //判断向下是否会别马脚
            {
                if (j == i)
                    continue;
                if (p[j].row == p[i].row + 1 && p[j].column == p[i].column)
                {
                    down = 1;
                    break;                          //如果别马脚,就结束
                }

            }
            if (0 == down)
            {
                if (p[i].column - 1 == b_column&&p[i].row + 2 == b_row)
                    return 0;
                else if (p[i].column + 1 == b_column&&p[i].row + 2 == b_row)
                    return 0;
            }
            break;


        }
    }
    return 1;
}

int yes_or_no(int b_row, int b_column, int size, qizhi*  p)               //判断有没有被将死,将死返回false,没死返回true
{
    int up = 0, down = 0, left = 0, right = 0;
    if (b_row - 1 > 0)                         //判断向上走会不会死
    {
        for (int i = 0; i < size; ++i)
        {
            if (p[i].column == b_column&&p[i].row == b_row - 1)      //判断黑将去的地方有没有红棋的子如果有吃掉
            {
                p[i].kind = ' ';
                break;
            }
        }
        up = panduan(b_row - 1, b_column, size, p);
    }
    if (b_row + 1 < 4)                                   //判断向下走会不会死
    {
        for (int i = 0; i < size; ++i)
        {
            if (p[i].column == b_column&&p[i].row == b_row + 1)      //判断黑将去的地方有没有红棋的子如果有吃掉
            {
                p[i].kind = ' ';
                break;
            }
        }
        down = panduan(b_row + 1, b_column, size, p);
    }
    if (b_column - 1 > 3)                               //判断向左走会不会死
    {
        for (int i = 0; i < size; ++i)
        {
            if (p[i].column == b_column - 1 && p[i].row == b_row)      //判断黑将去的地方有没有红棋的子如果有吃掉
            {
                p[i].kind = ' ';
                break;
            }
        }
        left = panduan(b_row, b_column - 1, size, p);
    }
    if (b_column + 1 < 7)                       //判断向右走会不会死
    {
        for (int i = 0; i < size; ++i)
        {
            if (p[i].column == b_column + 1 && p[i].row == b_row)      //判断黑将去的地方有没有红棋的子如果有吃掉
            {
                p[i].kind = ' ';
                break;
            }
        }
        right = panduan(b_row, b_column + 1, size, p);
    }
    return up + down + left + right;
}

int main()
{
    ///*文件重定向,输出测试*/
    //ifstream fin;
    //fin.open("data.in");
    //cin.rdbuf(fin.rdbuf());
    //ofstream out;
    //out.open("data.out");
    //cout.rdbuf(out.rdbuf());
    int r_number = 0, b_row = 0, b_column = 0;        //红方棋字个数,黑方将的位置
    while (cin >> r_number >> b_row >> b_column&&r_number != 0 && b_column != 0 && b_row != 0)
    {
        auto p = new qizhi[r_number];
        for (int i = 0; i < r_number; ++i)
        {
            cin >> p[i].kind >> p[i].row >> p[i].column;
        }
        if (yes_or_no(b_row, b_column, r_number, p))
            cout << "NO" << endl;
        else
            cout << "YES" << endl;
        delete[] p;

    }


}

  前面的题目的一些代码在gihub的仓库里https://github.com/YinAoXiong/Algorithmic-exercises,(全部都是用vs2015写的工程文件,源文件在同名的子目录目录中)。如有不对的地方欢迎大家评论指正,这里是我在github上的一个博客,感兴趣的可以去看一下哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值