liuli688
2024-01-08 17:31:28
其实这道题如果代码写好了还是很简单的。
如果白方能赢,则黑王此时所在和周围 CHECKMATE
。
所以,只要模拟标出白车和白王的攻击范围即可。代码如下。
#define STR string
#define BK break
#define CTN continue
#define FP(i,a,b) for(i = a;i < b;i++)
#define FM(i,a,b) for(i = a;i > b;i--)
#define FL(i,a,b) for(i = a;i <= b;i++)
#define FG(i,a,b) for(i = a;i >= b;i--)
STR r1,r2,wk,bk;
int xx,yy,i,j;
bool c[8][8],atk[8][8];//c 是标记是否有棋子,atk 是攻击范围
void markr(int x,int y)//标记车
{
FG(i,x,0)
{
if(i == x)//注意棋子本身不在攻击范围内
CTN;
else
atk[i][y] = true;
if(c[i][y])//如果碰到棋子,跳出,赋值后判定保证棋子本身会被覆盖到
BK;
}
FP(i,x,8)
{
if(i == x)
CTN;
else
atk[i][y] = true;
if(c[i][y])
BK;
}
FG(i,y,0)
{
if(i == y)
CTN;
else
atk[x][i] = true;
if(c[x][i])
BK;
}
FP(i,y,8)
{
if(i == y)
CTN;
else
atk[x][i] = true;
if(c[x][i])
BK;
}
}
void markk(int x,int y)//标记白王
{
FL(i,-1,1)
FL(j,-1,1)
{
xx = x + i;
yy = y + j;
if(xx >= 0 && xx < 8 && yy >= 0 && yy < 8)//防止 RE
atk[xx][yy] = true;
}
atk[x][y] = false;//棋子同样不在攻击范围内
}
但是,棋子的攻击范围可能会被其它棋子阻挡。上文的代码由于棋子本身不在攻击范围内,所以黑王可以通过吃掉白子来生存。由于碰到棋子后的跳出在赋值后,判定保证棋子本身会被覆盖到。所以棋子如果处在另一个棋子的攻击范围内黑王不能吃。
然后,就是开始的输入、标记和判定。
void check(int x,int y)
{
FL(i,-1,1)
FL(j,-1,1)
{
xx = x + i;
yy = y + j;
if(xx >= 0 && xx < 8 && yy >= 0 && yy < 8)//注意此处 9 个格子均需判定
if(!atk[xx][yy])
{
OUT("OTHER");
return ;
}
}
OUT("CHECKMATE");//如果全在攻击范围内,输出 CHECKMATE
}
MAIN
{
SPEEDUP;
IN(r1 >> r2 >> wk >> bk);
c[r1[0]-'a'][r1[1]-'1'] = true;//标记棋子
c[r2[0]-'a'][r2[1]-'1'] = true;
c[wk[0]-'a'][wk[1]-'1'] = true;
c[bk[0]-'a'][bk[1]-'1'] = true;
markr(r1[0]-'a',r1[1]-'1');//车
markr(r2[0]-'a',r2[1]-'1');
markk(wk[0]-'a',wk[1]-'1');//白王
check(bk[0]-'a',bk[1]-'1');//判定
END;
}
这段代码看起来很完美,于是提交。CF 上结果如下。
7
Time: 0 ms, memory: 4 KB
Verdict: WRONG_ANSWER
Input
a1 a2 c4 c2
Participant's output
OTHER
Jury's answer
CHECKMATE
Checker comment
wrong answer 1st words differ - expected: 'CHECKMATE', found: 'OTHER'
WA 了。手动模拟一下攻击范围(R
表示车,W
表示白王,B
表示黑王,x
表示攻击范围)
12345678
aRR------
bxxxxx...
cxBxKx...
dx.xxx...
ex.......
fx.......
gx.......
hx.......
我们发现,d2 这个位置没有被覆盖,事实上王即使走到了 d2 也会暴露在 a2 的车下面。于是我们作如下改动:
MAIN
{
SPEEDUP;
IN(r1 >> r2 >> wk >> bk);
c[r1[0]-'a'][r1[1]-'1'] = true;//标记棋子
c[r2[0]-'a'][r2[1]-'1'] = true;
c[wk[0]-'a'][wk[1]-'1'] = true;
//c[bk[0]-'a'][bk[1]-'1'] = true;注释掉,代表黑王即使移动也会暴露在攻击范围下
markr(r1[0]-'a',r1[1]-'1');//车
markr(r2[0]-'a',r2[1]-'1');
markk(wk[0]-'a',wk[1]-'1');//白王
check(bk[0]-'a',bk[1]-'1');//判定
END;
}
于是就 AC 啦!
#define MAIN signed main()
#define SPEEDUP ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define USING using namespace std
#define END return 0
#define LL long long
#define ULL unsigned long long
#define LD long double
#define STR string
#define EL '\n'
#define BK break
#define CTN continue
#define INF INT_MAX
#define UINF INT_MIN
#define IN(n) cin >> n
#define OUT(n) cout << n
#define OUTL(n) cout << n << EL
#define FP(i,a,b) for(i = a;i < b;i++)
#define FM(i,a,b) for(i = a;i > b;i--)
#define FL(i,a,b) for(i = a;i <= b;i++)
#define FG(i,a,b) for(i = a;i >= b;i--)
#include <bits/stdc++.h>
USING;
STR r1,r2,wk,bk;
int xx,yy,i,j;
bool c[8][8],atk[8][8];
void markr(int x,int y)
{
FG(i,x,0)
{
if(i == x)
CTN;
else
atk[i][y] = true;
if(c[i][y])
BK;
}
FP(i,x,8)
{
if(i == x)
CTN;
else
atk[i][y] = true;
if(c[i][y])
BK;
}
FG(i,y,0)
{
if(i == y)
CTN;
else
atk[x][i] = true;
if(c[x][i])
BK;
}
FP(i,y,8)
{
if(i == y)
CTN;
else
atk[x][i] = true;
if(c[x][i])
BK;
}
}
void markk(int x,int y)
{
FL(i,-1,1)
FL(j,-1,1)
{
xx = x + i;
yy = y + j;
if(xx >= 0 && xx < 8 && yy >= 0 && yy < 8)
atk[xx][yy] = true;
}
atk[x][y] = false;
}
void check(int x,int y)
{
FL(i,-1,1)
FL(j,-1,1)
{
xx = x + i;
yy = y + j;
if(xx >= 0 && xx < 8 && yy >= 0 && yy < 8)
if(!atk[xx][yy])
{
OUT("OTHER");
return ;
}
}
OUT("CHECKMATE");
}
MAIN
{
SPEEDUP;
IN(r1 >> r2 >> wk >> bk);
c[r1[0]-'a'][r1[1]-'1'] = true;
c[r2[0]-'a'][r2[1]-'1'] = true;
c[wk[0]-'a'][wk[1]-'1'] = true;
markr(r1[0]-'a',r1[1]-'1');
markr(r2[0]-'a',r2[1]-'1');
markk(wk[0]-'a',wk[1]-'1');
check(bk[0]-'a',bk[1]-'1');
END;
}