習題 4-1 象棋
阿新 • • 發佈:2018-11-01
我的程式碼僅過了題目資料。
思路:窮舉黑方【將】的下一步(上下左右),
如果某一步沒被將,則說明紅方沒有將死黑方,輸出NO
否則如果黑方【將】所有能被走的方向都被將,輸出YES
題目地址:https://vjudge.net/problem/UVA-1589
結果圖:
程式碼:
#include<iostream> #include<cstring> using namespace std; char c[11][10]; //棋盤 從(1,1)開始 bool win=false; bool f(int xx,int yy){ //被將軍返回true bool flag=true; int x,y; //左 x=xx; y=yy; for(int i=y+1;i<10;i++){ if(c[x][i]=='R'){ //遇到車 flag=false; break; } else if(c[x][i]=='H'||c[x][i]=='C'||c[x][i]=='C'){ int tag=1; int j=i+1; bool tag1=false; while(j<=10){ if(c[x][j]=='C') //馬後炮 tag+=1; else if(c[x][j]=='R'||c[x][j]=='H'){ tag=3; } if(tag==2){ flag=false; tag1=true; break; } else if(tag==3) break; j++; } if(tag1) break; } } //下 x=xx; y=yy; for(int i=x+1;i<=10;i++){ if(c[i][y]=='R'){ //遇到車 flag=false; break; }else if(c[i][y]=='H'||c[i][y]=='C'||c[i][y]=='C'){ int tag=1; int j=i+1; bool tag1=false; while(j<=10){ if(c[j][y]=='C') //馬後炮 tag+=1; else if(c[j][y]=='R'||c[j][y]=='H'){ tag=3; } if(tag==2){ flag=false; tag1=true; break; } else if(tag==3) break; j++; } if(tag1) break; } } //右 x=xx; y=yy; for(int i=y-1;y>=1;y--){ if(c[x][i]=='R'){ flag=false; break; } else if(c[x][i]=='H'||c[x][i]=='C'||c[x][i]=='C'){ int tag=1; int j=i-1; bool tag1=false; while(j>=1){ if(c[x][i]=='C') //馬後炮 tag+=1; else if(c[x][i]=='R'||c[x][i]=='H'){ tag=3; } if(tag==2){ flag=false; tag1=true; break; } else if(tag==3) break; j--; } if(tag1) break; } } //上 x=xx; y=yy; for(int i=x-1;i>=1;i--){ if(c[i][y]=='R'){ flag=false; break; } else if(c[i][y]=='H'||c[i][y]=='C'||c[i][y]=='C'){ int tag=1; int j=i-1; bool tag1=false; while(j>=1){ if(c[i][y]=='C') //馬後炮 tag+=1; else if(c[i][y]=='R'||c[i][y]=='H'){ tag=3; } if(tag==2){ flag=false; tag1=true; break; } else if(tag==3) break; j--; } if(tag1) break; } } //馬的判斷 x=xx; y=yy; if(x==1){ if(c[x][y-1]=='0'){ if(c[x+1][y-2]=='H'){ flag=false; } } if(c[x+1][y]=='0'){ if(c[x+2][y-1]=='H'||c[x+2][y+1]=='H'){ flag=false; } } if(c[x][y+1]=='0'){ if(c[x+1][y+2]=='H'){ flag=false; } } }else if(x==2){ if(c[x][y-1]=='0'){ if(c[x+1][y-2]=='H'||c[x-1][y-2]=='H'){ flag=false; } } if(c[x+1][y]=='0'){ if(c[x+2][y-1]=='H'||c[x+2][y+1]=='H'){ flag=false; } } if(c[x][y+1]=='0'){ if(c[x+1][y+2]=='H'||c[x-1][y+2]=='H'){ flag=false; } } }else if(x==3){ if(c[x-1][y]=='0'){ if(c[x-2][y-1]=='H'||c[x-2][y+1]=='H') flag=false; } if(c[x+1][y]=='0'){ if(c[x+2][y-1]=='H'||c[x+2][y+1]=='H'){ flag=false; } } if(c[x][y-1]=='0'){ if(c[x-1][y-2]=='H'||c[x+1][y-2]=='H'){ flag=false; } } if(c[x][y+1]=='0'){ if(c[x+1][y+2]=='H'||c[x-1][y+2]=='H') flag=false; } } //對將 x=xx; y=yy; int t=0; for(int i=x+1;i<=10;i++){ //飛車 if(c[i][y]!='0'&&c[i][y]!='G') t=1; if(c[i][y]=='G'&&t==0){ flag=false; break; } } if(!flag){ //被將軍返回true return true; } return false; } int main(){ int x,y; //將的位置 int n,x1,y1; char g; int temp_x,temp_y; //黑方將的座標 while(cin>>n>>x>>y&&n!=0&&x!=0&&y!=0){ memset(c,'0',sizeof(c)); //棋盤初始化 win=false; bool tagjiangjun=true; c[x][y]='B'; //黑方 將 for(int i=0;i<n;i++){ cin>>g>>x1>>y1; c[x1][y1]=g; } //列印棋盤 // for(int i=1;i<11;i++){ // for(int j=1;j<10;j++){ // cout<<c[i][j]; // } // cout<<endl; // } temp_x=x; temp_y=y; temp_y+=1; //向右移動 if(temp_y>=4&&temp_y<=6){ //判斷是否還被將軍 if(f(temp_x,temp_y)){ win=true; }else{ tagjiangjun=false; } } temp_x=x; temp_y=y; temp_x+=1; //向下 if(temp_x>=1&&temp_x<=3){ //判斷是否還被將軍 if(f(temp_x,temp_y)){ win=true; }else{ tagjiangjun=false; } } temp_x=x; temp_y=y; temp_y-=1; //向左 if(temp_y>=4&&temp_y<=6){ //判斷是否還被將軍 if(f(temp_x,temp_y)){ win=true; }else{ tagjiangjun=false; } } temp_x=x; temp_y=y; temp_x-=1; //向上 if(temp_x>=1&&temp_x<=3){ //判斷是否還被將軍 if(f(temp_x,temp_y)){ win=true; }else{ tagjiangjun=false; } } if(win&&tagjiangjun) cout<<"YES"<<endl; if(!tagjiangjun) cout<<"NO"<<endl; } return 0; }
網上看到的程式碼:
#include <cstdio> #define RD(X) if(s[X].x||s[X].y)s[X+1].x=x,s[X+1].y=y;else s[X].x=x,s[X].y=y #define CHECKR(X) (check(s[X],m,n)&&!between(s[X],m,n)) #define CHECKC(X) (check(s[X],m,n)&&between(s[X],m,n)==1) char c; int x,y,N; struct point{int x,y;}; point s[8];//B,G,R1,R2,H1,H2,C1,C2 int mx[4]={1,-1,0,0},my[4]={0,0,1,-1}; int abs(int tt){return ((tt<0)?-tt:tt);} int mid(int a1,int a2,int a3){return ((a1<a2&&a2<a3)||(a1>a2&&a2>a3));} int check(point TT,int x2,int y2){return ((TT.x==x2&&TT.y!=y2)||(TT.y==y2&&TT.x!=x2));} int between(point T,int x2,int y2){ int xx=0; for(int i=1;i<8;i++) xx+=(mid(T.x,s[i].x,x2)&&check(s[i],x2,y2))+(mid(T.y,s[i].y,y2)&&check(s[i],x2,y2)); return xx; } int checkH(point _T,int mm,int nn){ int dm=_T.x-mm,dn=_T.y-nn,am=abs(dm),an=abs(dn); return (am+an==3&&am&&an&&!between(_T,_T.x-(int(dm/2)<<1),_T.y-(int(dn/2)<<1))); } int Try(int m,int n){ if(m<1||m>3||n<4||n>6||\ (n==s[1].y&&!between(s[1],m,n))||\ CHECKR(2)||CHECKR(3)||\ CHECKC(6)||CHECKC(7))return 0; return !(checkH(s[4],m,n)||checkH(s[5],m,n)); } int main(){ while(~scanf("%d%d%d",&N,&s[0].x,&s[0].y)&&(N||s[0].x||s[0].y)){ for(int i=1;i<8;i++)s[i].x=s[i].y=0; while(N--){ scanf(" %c%d%d",&c,&x,&y); if(c=='G')s[1].x=x,s[1].y=y; if(c=='R')RD(2); if(c=='H')RD(4); if(c=='C')RD(6); } for(int i=0;i<4;i++) if(Try(s[0].x+mx[i],s[0].y+my[i])){printf("NO\n");goto lable;} printf("YES\n");lable:; } return 0; }
還有一種方法,把紅方棋子能走的全設為1,不能走的設為0,判斷黑方【將】上下左右。