演算法競賽入門經典 第二版 習題4-1 象棋 Xiangqi uva1589
阿新 • • 發佈:2019-02-11
卡了我一個周,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;
}