1. 程式人生 > >習題 4-1 象棋

習題 4-1 象棋

我的程式碼僅過了題目資料。

思路:窮舉黑方【將】的下一步(上下左右),

如果某一步沒被將,則說明紅方沒有將死黑方,輸出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,判斷黑方【將】上下左右。