1. 程式人生 > >演算法競賽入門經典 第二版 習題4-1 象棋 Xiangqi uva1589

演算法競賽入門經典 第二版 習題4-1 象棋 Xiangqi uva1589

卡了我一個周,WA到想哭,象棋盤放在臥室一個周沒收起來(┬_┬)

思路:將死,也就是說將向上下左右移動(如果可能的話)均仍被將軍。
我自然的想到了建一個二維陣列模擬棋盤,分別表示某行某列的棋子,然後將將上下左右移動(如果可能的話)後分別判斷是否會被車馬炮包括帥吃了。然而。。。迷之超時。。。3秒的執行時間竟然能超了。。。
一番調整之後仍舊超時,無奈重寫,換了個想法,用結構體儲存棋子的位置,判斷吃子時直接遍歷判斷棋子即可,這比遍歷棋盤迴圈次數少得多。

具體的判斷方法:
車/帥:本題中帥與車的性質相同,若有車/帥與將之間在同一行或同一列且中間沒有棋子阻隔,則將被吃。
炮:若有車/帥與將之間在同一行或同一列且中間有一個棋子,則將被吃。
馬:將周圍有8個被馬吃的可能位點,若這些位置上有馬且不蹩馬腿,則將被吃。

注:(1)將可以吃掉相鄰的棋子,注意處理,遍歷時若有棋子與將移動後的位置相同,continue即可。
(2)輸入格式問題:這題測試資料怕是有問題,這問題坑的我懷疑人生。
2 1 4
G 10 5
R 6 4
讀取棋子的種類時我原本用的是scanf(“%*c%c”, &ch);
那個%*c吃的是回車符,我能用到的所有測試工具都能正常輸入正常輸出,然而OJ就是告訴我WA。
開始學了點c++之後改用cin >> ch;
然後就AC了這裡寫圖片描述

程式碼:c風格的c++

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; typedef struct { int x,y; } chess; int R,H,C; chess g,r[10],h[10],c[10]; //棋子讀入 void getchess() { char ch; // scanf("%*c%c", &ch); cin >> ch;//必須cin讀入(原因不明) switch(ch) { case 'R': scanf("%d%d", &r[R].x, &r[R].y); R++; break; case 'G'
: scanf("%d%d", &r[R].x, &r[R].y); R++; break; case 'H': scanf("%d%d", &h[H].x, &h[H].y); H++; break; case 'C': scanf("%d%d", &c[C].x, &c[C].y); C++; break; } } //判斷是否有棋子在此位置,用於判斷蹩馬腿的棋子 int loca_search(int a, int b) { int i; for(i=0;i<R;i++) { if(r[i].x==a&&r[i].y==b) { return 1; } } for(i=0;i<H;i++) { if(h[i].x==a&&h[i].y==b) { return 1; } } for(i=0;i<C;i++) { if(c[i].x==a&&c[i].y==b) { return 1; } } return 0; } //判斷某列有幾個棋子在minn行與maxx行之間,用於車帥炮的判斷 int y_search(int b, int minn, int maxx) { int i,cot=0; for(i=0;i<R;i++) { if(r[i].y==b&&r[i].x>minn&&r[i].x<maxx) { cot++; } } for(i=0;i<H;i++) { if(h[i].y==b&&h[i].x>minn&&h[i].x<maxx) { cot++; } } for(i=0;i<C;i++) { if(c[i].y==b&&c[i].x>minn&&c[i].x<maxx) { cot++; } } return cot; } //判斷某行有幾個棋子在minn列與maxx列之間,用於車帥炮的判斷 int x_search(int a, int minn, int maxx) { int i,cot=0; for(i=0;i<R;i++) { if(r[i].x==a&&r[i].y>minn&&r[i].y<maxx) { cot++; } } for(i=0;i<H;i++) { if(h[i].x==a&&h[i].y>minn&&h[i].y<maxx) { cot++; } } for(i=0;i<C;i++) { if(c[i].x==a&&c[i].y>minn&&c[i].y<maxx) { cot++; } } return cot; } //對馬判斷 int horse(int a, int b) { int i; for(i=0;i<H;i++) { if(a-2>=1) { if( (h[i].x==a-2&&h[i].y==b-1&&!loca_search(a-1,b-1)) || (h[i].x==a-2&&h[i].y==b+1&&!loca_search(a-1,b+1)) ) { return 1; } } if(a-1>=1) { if( (h[i].x==a-1&&h[i].y==b-2&&!loca_search(a-1,b-1)) || (h[i].x==a-1&&h[i].y==b+2&&!loca_search(a-1,b+1)) ) { return 1; } } if( (h[i].x==a+1&&h[i].y==b-2&&!loca_search(a+1,b-1)) || (h[i].x==a+1&&h[i].y==b+2&&!loca_search(a+1,b+1)) ) { return 1; } if( (h[i].x==a+2&&h[i].y==b-1&&!loca_search(a+1,b-1)) || (h[i].x==a+2&&h[i].y==b+1&&!loca_search(a+1,b+1)) ) { return 1; } } return 0; } //對炮判斷 int cannon(int a, int b) { int i,minn,maxx; for(i=0;i<C;i++) { if(c[i].x==a&&c[i].y==b) continue; if(c[i].x==a) { minn = c[i].y<b?c[i].y:b; maxx = c[i].y>b?c[i].y:b; if(x_search(a,minn,maxx)==1) { return 1; } } if(c[i].y==b) { minn = c[i].x<a?c[i].x:a; maxx = c[i].x>a?c[i].x:a; if(y_search(b,minn,maxx)==1) { return 1; } } } return 0; } //對車帥判斷 int chariot(int a, int b) { int i,minn,maxx; for(i=0;i<R;i++) { if(r[i].x==a&&r[i].y==b) continue; if(r[i].x==a) { minn = r[i].y<b?r[i].y:b; maxx = r[i].y>b?r[i].y:b; if(x_search(a,minn,maxx)==0) { return 1; } } if(r[i].y==b) { minn = r[i].x<a?r[i].x:a; maxx = r[i].x>a?r[i].x:a; if(y_search(b,minn,maxx)==0) { return 1; } } } return 0; } //判斷將位於a行b列是是否被吃 int judge(int a, int b) { if(chariot(a,b)) { return 1; } if(cannon(a,b)) { return 1; } if(horse(a,b)) { return 1; } return 0; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,t; while(scanf("%d%d%d", &n, &g.x, &g.y)) { if(n==0) { break; } R = 0; H = 0; C = 0; memset(r,0,sizeof(r)); memset(h,0,sizeof(h)); memset(c,0,sizeof(c)); while(n--) { getchess(); } t = 1; if(g.y!=4) { t = judge(g.x,g.y-1); } if(g.y!=6&&t==1) { t = judge(g.x,g.y+1); } if(g.x!=1&&t==1) { t = judge(g.x-1,g.y); } if(g.x!=3&&t==1) { t = judge(g.x+1,g.y); } if(t==0) { printf("NO\n"); } else { printf("YES\n"); } } return 0; }