首页 > 其他 > 详细

HDU 4121 Xiangqi 模拟

时间:2015-08-17 15:32:40      阅读:73      评论:0      收藏:0      [点我收藏+]

原题: http://acm.hdu.edu.cn/showproblem.php?pid=4121

题目大意:
对于给定的棋盘,黑棋只有一个,红棋有n个,现在黑将可以走一步,如果怎么走都活不了,就是被将死了,输出YES。

这道题我们只需要模拟每个红棋的攻击范围,最后看黑将的能走的地方是否在攻击范围就可以了。

#include <iostream>
#include"cstdio"
#include"stdlib.h"
#include"string.h"
using namespace std;

int main()
{
    //freopen("in.txt","r",stdin);
    int mp[12][11];
    int t,sx,sy;
    while(scanf("%d %d %d",&t,&sx,&sy)!=EOF)
    {
        if(t==0&&sx==0&&sy==0)    break;
        memset(mp,0,sizeof(mp));
        while(t--)
        {
            int x,y;
            char s[10];
            scanf("%s %d %d",s,&x,&y);
            //因为帅和车的攻击范围一样,所以我们这里把帅和车看作同一种棋
            if(s[0]==‘G‘)//帅
                mp[x][y]=2;
            else if(s[0]==‘R‘)//车
                mp[x][y]=2;
            else if(s[0]==‘H‘)//马
                mp[x][y]=3;
            else if(s[0]==‘C‘)//炮
                mp[x][y]=4;
        }
        //用来存储攻击范围
        bool flag[11][10];
        memset(flag,false,sizeof(flag));
        //遍历每个点
        for(int i=1; i<=10; i++)
        {
            for(int j=1; j<=9; j++)
            {
            //枚举每一种棋
                if(mp[i][j]==2)
                {
                    //向右
                    for(int k=j+1; k<=9; k++)
                    {
                        //该方向的所有点都该为被攻击区域
                        flag[i][k]=1;
                        //除非遇到有棋子遮挡,但那个棋子的位置是可以被攻击的,
                        //后面的位置才不会被攻击,所以这里先标记再判断,
                        //防止黑将的下一步可以吃掉你那里的棋子,但
                        //是那个棋子之前占的地方并不在你的攻击范围内
                        if(mp[i][k])
                            break;
                    }
                    //向左
                    for(int k=j-1; k>=1; k--)
                    {
                        flag[i][k]=1;
                        if(mp[i][k])
                            break;
                    }
                    //向下
                    for(int k=i+1; k<=10; k++)
                    {
                        flag[k][j]=1;
                        if(mp[k][j])
                            break;
                    }
                    //向上
                    for(int k=i-1; k>=1; k--)
                    {
                        flag[k][j]=1;
                        if(mp[k][j])
                            break;
                    }
                }
                //考虑到出界问题,所以这里分成8种情况
                //实际上把数组数组往右下角再平移一格就不用担心了
                //但是那样写代码有点痛苦
                else if(mp[i][j]==3)
                {
                    //向左上
                    if(mp[i][j-1]==0&&j>=3&&i>=2)
                    {
                        flag[i-1][j-2]=1;
                    }
                    //向左下
                    if(mp[i][j-1]==0&&j>=3&&i<=9)
                    {
                        flag[i+1][j-2]=1;
                    }
                    //向右上
                    if(mp[i][j+1]==0&&j<=8&&i>=2)
                    {
                        flag[i-1][j+2]=1;
                    }
                    //向右下
                    if(mp[i][j+1]==0&&j<=8&&i<=9)
                    {
                        flag[i+1][j+2]=1;
                    }
                    //向上左
                    if(mp[i-1][j]==0&&i>=3&&j>=2)
                    {
                        flag[i-2][j-1]=1;
                    }
                    //向上右
                    if(mp[i-1][j]==0&&i>=3&&j<=8)
                    {
                        flag[i-2][j+1]=1;
                    }
                    //向下左
                    if(mp[i+1][j]==0&&i<=7&&j>=2)
                    {
                        flag[i+2][j-1]=1;
                    }
                    //向下右
                    if(mp[i+1][j]==0&&i<=7&&j<=8)
                    {
                        flag[i+2][j+1]=1;
                    }
                }
                else if(mp[i][j]==4)
                {
                    int tflag=0;
                    //向右
                    for(int k=j+1; k<=9; k++)
                    {
                        //当前没有炮架子的时候并扫描到了有棋可以当架子
                        if(tflag==0&&mp[i][k]!=0)
                            tflag=1;
                        //有架子后面的都是被攻击范围
                        else if(tflag==1)
                        {
                            flag[i][k]=1;
                            //一旦遇到有棋的地方,该棋是在攻击范围内的,
                            //但是后面的不在了,所以要跳出循环
                            if(mp[i][k])    break;
                        }

                    }
                    tflag=0;
                    //向左
                    for(int k=j-1; k>=1; k--)
                    {
                        if(tflag==0&&mp[i][k]!=0)
                            tflag=1;
                        else if(tflag==1)
                        {
                            flag[i][k]=1;
                            if(mp[i][k])    break;
                        }
                    }
                    tflag=0;
                    //向下
                    for(int k=i+1; k<=10; k++)
                    {
                        if(tflag==0&&mp[k][j]!=0)
                            tflag=1;
                        else if(tflag==1)
                        {
                            flag[k][j]=1;
                            if(mp[k][j])    break;
                        }
                    }
                    tflag=0;
                    //向上
                    for(int k=i-1; k>=1; k--)
                    {
                        if(tflag==0&&mp[k][j]!=0)
                            tflag=1;
                        else if(tflag==1)
                        {
                            flag[k][j]=1;
                            if(mp[k][j])    break;
                        }
                    }
                }
            }
        }
        //将地图上黑方城外都标记为攻击区域,就是说走出界也是在攻击范围内
        for(int i=4;i<=6;i++)
        {
            flag[0][i]=1;
            flag[4][i]=1;
        }
        for(int i=1;i<=3;i++)
        {
            flag[i][3]=1;
            flag[i][7]=1;
        }
//        for(int i=0; i<=11; i++)
//        {
//            for(int j=0; j<=10; j++)
//            {
//                printf("%d ",flag[i][j]);
//            }
//            printf("\n");
//        }
        //当4边都是攻击范围就GG了
        if(flag[sx+1][sy]&&flag[sx-1][sy]&&flag[sx][sy+1]&&flag[sx][sy-1])
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 4121 Xiangqi 模拟

原文:http://blog.csdn.net/qq_27508477/article/details/47725203

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!