#include
using namespace std;
void solve()
{
int h,w,xa,ya,xb,yb;
cin>>h>>w>>xa>>ya>>xb>>yb;
if(xa==xb)
{
cout<<"Draw"<<endl;
return;
}
if(xa>xb)
{
cout<<"Draw"<<endl;
return;
}
if(xb-xa==1)
{
if(abs(ya-yb)<=1)
cout<<"Alice"<<endl;
else
cout<<"Draw"<<endl;
return;
}
int cnt=0;
int la=ya,ra=ya,lb=yb,rb=yb;
while(xa<xb)
{
if(xb-xa==1)
break;
cnt++;
if(cnt&1)
{
xa++;
if(la>1)
la--;
if(ra<w)
ra++;
}
else
{
xb--;
if(lb>1)
lb--;
if(rb<w)
rb++;
}
}
// cout<
// cout<
if((cnt+1)&1)
{
if(la>1)
la--;
if(ra<w)
ra++;
if(ra>=rb&&la<=lb)
cout<<"Alice"<<endl;
else
cout<<"Draw"<<endl;
}
else
{
if(lb>1)
lb--;
if(rb<w)
rb++;
if(rb>=ra&&lb<=la)
cout<<"Bob"<<endl;
else
cout<<"Draw"<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--)
solve();
return 0;
}
做该题的时候想过很多次看题解,但是强迫自己没看题解,慢慢地想,然后改代码调试,弄了一个半小时过了
我的思路是,判断一下两个棋子只相差一行的时候的情况,维护一个左右边界,表示的是可能选择的点,假设操作的次数是奇数,表示应该轮到 A l i c e Alice Alice 下棋了,操作的次数是偶数,表示应该轮到 B o b Bob Bob 操作了
假设某一个人的下棋的区间可以完全覆盖另一个人的区间,表示这个人可以获得胜利,否则就是平局(这个可以画图来理解),假设不是完全覆盖,按照最优策略,另一个人可以选择往不被覆盖的点去操作
最优策略是根据两个棋子只相差一行的时候,轮到谁下来进行调整的
刚开始想的是用 c n t cnt cnt 表示回合数,也就是两个人各操作一次,但是我后面发现不方便,因为不能确定一定是偶数的操作次数就截止了,表示起来麻烦一些
用 c n t cnt cnt 表示操作的次数,边界更新的时候需要严格大于,严格小于,我是输出调试的时候发现左边界出现了 0 0 0 ,发现的这个问题,每一次操作更新边界的同时也更新行数
最后一次操作的时候更新边界,判断区间的包含关系
前面加了很多特判,比如说两个点相差一行,纵坐标之间的差的绝对值小于等于 1 1 1 的话,一定是第一个人胜利,两个点在同一行的话,一定是平局,如果不可能相交的话,也一定是平局
#include
using namespace std;
void solve()
{
int h,w,xa,ya,xb,yb;
cin>>h>>w>>xa>>ya>>xb>>yb;
if(xa>=xb)
{
cout<<"Draw"<<endl;
return;
}
int cnt=0;
int la=ya,ra=ya,lb=yb,rb=yb;
while(xa<xb)
{
if(xb-xa==1)
break;
cnt++;
if(cnt&1)
{
xa++;
if(la>1)
la--;
if(ra<w)
ra++;
}
else
{
xb--;
if(lb>1)
lb--;
if(rb<w)
rb++;
}
}
if((cnt+1)&1)
{
if(la>1)
la--;
if(ra<w)
ra++;
if(ra>=rb&&la<=lb)
cout<<"Alice"<<endl;
else
cout<<"Draw"<<endl;
}
else
{
if(lb>1)
lb--;
if(rb<w)
rb++;
if(rb>=ra&&lb<=la)
cout<<"Bob"<<endl;
else
cout<<"Draw"<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--)
solve();
return 0;
}
改成这样会更简洁一点,有一些特判其实是包含在后面的一般做法里面的,准确的来说就是思路清晰一些,代码就会简短一些,但无论如何,能通过的代码就是好代码
所以该题最难的点是,什么时候谁会获得胜利,算是一个博弈论,要么是完全覆盖,胜利,要么就是平局,部分覆盖不算赢,这一个点比较难想清楚
因为部分覆盖的话,另一个选手完全可以选择往没有覆盖的部分去走,需要走下一步的选手无法走到另一个选手的棋子上去,这一次操作过后,两个棋子错开了,一定是平局,再也没有相交的可能
总的来说,写出来这个题给我的正反馈挺强的