昨晚codeforces的E题。哼,有趣的题目,她引起了我的注意

1 篇文章 0 订阅
1 篇文章 0 订阅

题目链接: Problem - E - Codeforces

题目背景:双方都绝对理智,让你预测结果的题目。

  • 首先,有A和B两个人,各有一个棋子在棋盘中,棋盘大小为X,Y。
  • 每一轮,A的棋子要往下走一格,假设现在在(x,y),它可以走到(x+1,y)或者(x+1,y-1)或者(x+1,y+1);而B的棋子要往上走一格,假设现在在(x,y),它可以走到(x-1,y)或者(x-1,y-1)或者(x-1,y+1)。(这里限制棋子只能走在棋盘格子中)
  • 初始两个棋子互不重叠,A先手。
  • 在绝对理智的走法情况下,最终,如果A棋子(白棋)可以吃掉B棋子(黑棋),则A胜利;B的棋子吃掉A的,则B胜利;最后吃不掉对方,则平局。

img

这个输入,6 5 2 2 5 3

6行5列,A的棋子在2行2列,B棋子在 5行3列。

  1. 我们首先分析只有一列的情况:

img
因为A必定向下走一行(可能是斜着走,也可能是直走,但是行数必定加一),而B必定往上走一行(行数必定减一)。可以比较简单的看出,在中间间隔的行数为偶数时,B会赢,反之,奇数时, A会赢。(注意!在计算时,xb-xa的到的结果是,间隔数+1)。

  • 然后我们发现,题目中会有平局的情况。
  1. 我们可以考虑到了列数不是1的情况:

  • 通过例子1,我们也可以发现,其实,当两者的起点的行数确定了,他们相遇的行数也确定了。
  • 我们可以大概的想象出,如果你是那个会输的人,那么你能争取的最好结果是平局。又因为对方也可以斜着走,于是我们可以知道,如果是列上和对方正对着,或者列号与对方相差-1,都没有逃脱的机会。于是我们的策略是,往左或者右,一个方向走到底,看看能不能逃过对方的范围。

img

可以看到xb - xa = 3的,相遇时,A走了2步,B走了1步。

可以看到xb - xa = 4的,相遇时,A走了2步,B走了2步。

这样可以算出双方能走到的最大的范围,进而确定,那个会输的是否能不被吃,进而得到平局。

  1. 特殊情况:

A本来就和B在同一行,或者,行数大于B。代码表示:xa>=xb,这种情况,只能是平局。

代码:

#include<bits/stdc++.h>

using namespace std;


 void solve(){
   int x,y;
   cin>>x>>y;
   int a,aa,b,bb;
   cin>>a>>aa>>b>>bb;

   bool f = 0;
   if(a>=b){
 //     cout<<"1"<<"\n";
     cout<<"Draw";
     return;
   }
   else{
     int k = b-a;
     if((k&1)==0){// b可能赢,或者平 
       f = 1; 
     }
     
     int am,ax,bm,bx;
     // 多少步后相遇。 
     int ka = (k+1)/2;
     int kb = k-ka;
 //     cout<<"ka="<<ka<<"\n";
 //     cout<<"kb="<<kb<<"\n";
     // 算出最远跑多远。 
     am = max(aa-ka,1);
     ax = min(aa+ka,y);
     bm = max(bb-kb,1);
     bx = min(bb+kb,y);
     
     bool fm = am<bm;
     bool fx = ax>bx;
     
     bool ffm = bm<am;//am<bm-1//am>bm
     bool ffx = bx>ax;
     if(f){
       if(fx||fm){
         cout<<"Draw";
       }
       else{
         cout<<"Bob";
       }
     }
     else{
       if(ffx||ffm){
         cout<<"Draw";
       }
       else{
         cout<<"Alice";
       }
     }
   }

   

 } 
 int main(){
   int n;
   cin>>n;
   while(n--){
     solve();
     cout<<"\n";
   }


   return 0;
 } 
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值