题目
有n块xi*yi的巧克力,
Alice(先手)可以选一块xi*yi的巧克力,
并把它切成p*yi和q*yi(p+q==xi)两块巧克力,
而Bob可以选一块xj*yj的巧克力,
并把它切成xj*u和xj*v(u+v==yj)两块巧克力,
简单来说,就是Alice竖着切而Bob横着切,
给定局面,最优抉择,问谁必胜
思路来源
https://blog.csdn.net/qq_34374664/article/details/52959986
题解
首先注意到,对于一块xi*yi的巧克力,Bob可以切(yi-1)刀
Alice无论怎么切第一刀,都会使Bob增加(yi-1)刀
而如果Alice切成了(2,xi-2),那么Bob选择那块2*yi的巧克力切一刀,就可以只给Alice增加1刀
在Alice无法改变第一刀给对方加的刀数的情况下,应该贪心地让对方给自己加的刀数最多
所以Alice应该挑中间切,使最坏情况最优(有点像Alpha-Beta剪枝)
切成,这样Bob就会选择*yi这一块,给Alice加刀
Bob也会类似地贪心选,切在中间的位置
而此刻,巧克力分成了左上角,左下角,和右边半块三块
Alice下一次抉择,应该选这三块里y最小的那块,这样一刀会让Bob加的刀数最少
所以Alice会选择左上角那块(或左下角那块,y一样的),也就是最小的那块
Bob会递归进行该过程,选择Alice刚切完的两块的最小的那块
直至有一块变成了形如r*1或1*r的巧克力C,
此时无论一方怎么切都不会给对方加刀数,可以无忧无虑地切(r-1)次
而另一方既然在最小的C这块巧克力里输了,不能切了
如果主动去切该过程中多出来的别的巧克力DEFGH…,就一定会在剩下的巧克力里输
(优先给对方加刀,给对方加的刀少的都输了,给对方加的多了不输的更惨么)
所以这块巧克力就废了,我们类似处理别的巧克力,直至所有大巧克力的最小块都不可再分
此时,如果先手不得不处理形如DEFGH的巧克力,先手败;否则后手败
这个感觉就是下象棋兵和卒都没过河互差两步,别的棋没棋走了走兵卒不肯定会被拱掉么
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int t,n,x,y;
ll a,b;
int main()
{
scanf("%d",&t);
for(int k=1;k<=t;++k)
{
scanf("%d",&n);
a=b=0;
for(int i=0;i<n;++i)
{
scanf("%d%d",&x,&y);
while(x>1&&y>1)x/=2,y/=2;
if(y==1)a+=(x-1);
if(x==1)b+=(y-1);
}
printf("Case %d: ",k);
puts(a>b?"Alice":"Bob");
}
return 0;
}