题目:https://vjudge.net/problem/UVA-1589
卡了我一个周,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;
}
本文分享了解决UVA-1589问题的心得,通过使用结构体存储棋子位置并遍历判断吃子情况,有效避免了超时问题。文章详细介绍了如何判断不同棋子对“将”的威胁,并特别提到了输入格式的陷阱。
6822

被折叠的 条评论
为什么被折叠?



