hdu3544 Alice's Game(博弈/贪心)

题目

有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剪枝)

切成([\tfrac{x_{i}}{2}],x_{i}-[\tfrac{x_{i}}{2}]),这样Bob就会选择[\tfrac{x_{i}}{2}]*yi这一块,给Alice加[\tfrac{x_{i}}{2}]-1

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;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值