hdu4121 象棋checkmate模拟

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

几百年前就做过这道题了,没想到坑到这个地步了。。。。。

很简单,就是判断一个黑先手的局面是否checkmate(黑必败局,红必胜终局)

随便秀一下写程序之前的草稿


/*1.黑先红后
2.黑无论,红有胜
3.两种棋子,帅马将    车炮帅
4.检查棋盘合法性  不跃出棋盘
5.独立合法
范围 路径 终点
数组走法路径:
帅将有范围 马的不蹩脚 红的终点不红
飞行路径:
四方扫
红的终点不同红
帅车遇到红-1/+1或者黑为界限
炮隔一个两个为界限 
帅同列吃
6.eat检测 有无将
7.一个棋子遗留局面vector
int blockcnt  统计某一个方向有多少个棋子阻碍着
int check(红的不红,帅范围)
vec go()
int solve()
{
  for 黑子
  for红子
}*/
View Code

ac代码 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<string>
#include<cctype>
#include<stack>
#include<queue>
#include<set>
#include<sstream>
#include<map>
#include<ctime>
using namespace std;
#define For(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,k,n) for(int i=n;i>=k;i--)
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define NEG(a) memset(a,-1,sizeof(a));
#define FILL(a) memset(a,0x3f,sizeof(a));
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define print(b,a) cout<<b<<"="<<a<<endl;
#define printbin(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;}
#define printarr(i,a,f,b) {For(i,f,b) printf("%d ",a[i]); printf("\n");}


#define bg -1
#define rg 1
#define cr 2
#define cn 3
#define hr 4
struct node
{
    int t[11][10];
};
int check(node nd,int r,int c,int nr,int nc)
{
    if(nd.t[r][c]>0&&nd.t[nr][nc]>0) 
        return 0;
    else if(nd.t[r][c]==rg&&(nr<=7||nr>=11||nc<=3||nc>=7)) 
        return 0;
    else if(nd.t[r][c]==bg&&(nr<=0||nr>=4||nc<=3||nc>=7)) 
        return 0;
    else if(nr<=0||nr>=11||nc<=0||nc>=10) 
        return 0;
    else 
        return 1;
}
int blockcnt(node nd,int r,int c,int l,int u,int flg)
{
    if(l>u) swap(l,u);
    int d=0,cnt=0;
    if(flg==1) d=(nd.t[u][c]!=0)+(nd.t[l][c]!=0);
    if(flg==0) d=(nd.t[r][u]!=0)+(nd.t[r][l]!=0);
    //printf("flg=%d d=%d\n",flg,d);
    For(k,l,u) 
    {
        if(flg==0)
        {
            if(nd.t[r][k])
            {
                cnt++;
            }
        }   
        else
        {
            if(nd.t[k][c])
            {
                cnt++;
            }
        }
    }
    cnt-=d;
    //printf("r=%d c=%d l=%d u=%d cnt=%d\n",r,c,l,u,cnt);
    return cnt;
}
int alive(node nd)
{
    int flg=0;
    For(i,1,10)
    {
        For(j,1,9)
        {
            if(nd.t[i][j]==bg)
                flg=1;
        }
    }
    return flg;
}
vector<node>go(node nd,int r,int c) //move i,j
{
    int tp=nd.t[r][c];
    vector<node>st;
    if(tp==bg||tp==rg)
    {
        int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
        For(k,0,3)
        {
            int nr=r+d[k][0],nc=c+d[k][1];
            //printf("nr=%d nc=%d\n",nr,nc);
            if(check(nd,r,c,nr,nc))
            {
                node nnd=nd;
                nnd.t[r][c]=0;
                nnd.t[nr][nc]=tp;
                st.push_back(nnd);
            }
        }
        For(nr,1,10)
        {
            if(nr==r) continue;
            else
            {
                if(nd.t[nr][c]==-tp
                    &&blockcnt(nd,r,c,r,nr,1)==0
                    )
                {
                    node nnd=nd;
                    nnd.t[r][c]=0;
                    nnd.t[nr][c]=tp;
                    st.push_back(nnd);
                }
            }
        }
    }
    else if(tp==cr)
    {
        For(nr,1,10)
        {
            if(nr==r) continue;
            if(blockcnt(nd,r,c,r,nr,1)==0
                    &&check(nd,r,c,nr,c)
                    )
                {
                    node nnd=nd;
                    nnd.t[r][c]=0;
                    nnd.t[nr][c]=tp;
                    st.push_back(nnd);
                }
        }
        For(nc,1,9)
        {
            if(nc==c) continue;
            if(blockcnt(nd,r,c,c,nc,0)==0
                    &&check(nd,r,c,r,nc)
                    )
                {
                    node nnd=nd;
                    nnd.t[r][c]=0;
                    nnd.t[r][nc]=tp;
                    st.push_back(nnd);
                }
        }
    }
    else if(tp==cn)
    {
        For(nr,1,10)
        {
            if(nr==r) continue;
            if(((nd.t[nr][c]&&blockcnt(nd,r,c,r,nr,1)==1)
                ||(!nd.t[nr][c]&&blockcnt(nd,r,c,r,nr,1)==0))
                    &&check(nd,r,c,nr,c)
                    )
                {
                    node nnd=nd;
                    nnd.t[r][c]=0;
                    nnd.t[nr][c]=tp;
                    st.push_back(nnd);
                }
        }
        For(nc,1,9)
        {
            if(nc==c) continue;
            if(((nd.t[r][nc]&&blockcnt(nd,r,c,c,nc,0)==1)
                ||(!nd.t[r][nc]&&blockcnt(nd,r,c,c,nc,0)==0))
                    &&check(nd,r,c,r,nc)
                    )
                {
                    node nnd=nd;
                    nnd.t[r][c]=0;
                    nnd.t[r][nc]=tp;
                    st.push_back(nnd);
                }
        }
    }
    else
    {
        int d[8][2]={{2,1},{2,-1},{-2,1},{-2,-1}
                    ,{1,2},{1,-2},{-1,2},{-1,-2}
                    };
        For(k,0,7)
        {
            int nr=r+d[k][0],nc=c+d[k][1];
            if(abs(d[k][0])==2)
            {
                int nnr=nr-d[k][0]/2;
                if(nd.t[nnr][c]) continue;
            }
            else
            {
                int nnc=nc-d[k][1]/2;
                if(nd.t[r][nnc]) continue;
            }
            if(check(nd,r,c,nr,nc))
            {
                node nnd=nd;
                nnd.t[r][c]=0;
                nnd.t[nr][nc]=tp;
                st.push_back(nnd);
            }
        }
    }
    //printf("sz=%d\n",st.size());
    return st;
}
int solve(node nd)
{
    int checkmate=1;
    For(i,1,10)
    {
        For(j,1,9)
        {
            if(nd.t[i][j]>=0) 
                continue;
            vector<node>st=go(nd,i,j);
            int sz=st.size();
            For(k,0,sz-1)
            {
                node _nd=st[k];
                //printf("father:\n");
                //For(r,1,10)
                    //printarr(c,st[k].t[r],1,9);
                int canwin=0;
                For(_i,1,10)
                {
                    For(_j,1,9)
                    {
                        if(nd.t[_i][_j]<=0)
                            continue;
                        vector<node>_st=go(_nd,_i,_j);
                        int _sz=_st.size();
                        For(_k,0,_sz-1)
                        {
                            //printf("%d %d son:\n",_i,_j);
                            //For(_r,1,10)
                                //printarr(_c,_st[_k].t[_r],1,9);
                            if(!alive(_st[_k])) 
                                canwin=1;
                        }
                    }
                }
                if(!canwin)
                    checkmate=0;
            }
        }
    }
    return checkmate;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int N,R,C;
    while(cin>>N>>R>>C&&!(N==0&&R==0&&C==0)){
        node init;
        MEM(init.t);
        init.t[R][C]=bg;
        For(i,1,N)
        {
            char cc;
            cin>>cc>>R>>C;
            int tp;
            if(cc=='G') tp=rg;
            else if(cc=='R') tp=cr;
            else if(cc=='C') tp=cn;
            else tp=hr;
            init.t[R][C]=tp; 
        }
        if(solve(init))
            puts("YES");
        else puts("NO");
    }
    return 0;
}
View Code

思路:

go函数返回当前局面可以的下一步局面的集合,check函数专门检查范围性的合法性,棋子特殊合法性由go解决,而棋子合法性中例如炮车需要的监测障碍由blockcnt解决,最后solve针对局面集合判断checkmate。

错误:

但是错误依然很多,于是采用了两两棋子构造简单数据,打印局面,检测各个棋子走法正确性的方法。

犯的错误包括忘记了象棋不吃子和车走法一样,没有考虑棋子不能不走,变量混淆,blockcnt没有考虑我把上下界调整了的情况等等。。。

启示:

启示就是模拟类的:1.打草稿 2.单元测试 3.变量厘清 4.功能分割,要写针对数据和状态的代码,不要写针对路径的代码。

 

喂 人脑是怎么这么快学会象棋的啊啊啊啊啊啊啊啊,我将个军都写得上气不接下气)

 

posted @ 2016-08-02 10:35  aidgn  阅读(293)  评论(0编辑  收藏  举报