HDU 4371 AliceBob之生成数列直到大于n或者小于等于S(i-2)-思维-(由已知条件推最优步骤)

题意:已知n、d1、d2....dm,Alice先生成一个数S1=0,Bob再生成一个数S2=S1+dk,之后他们生成的数遵循这样的条件:Si=S(i-1)+dk,或者Si=S(i-1)-dk,其中1<=k<=m,S(i-2)<Si<=n。最先写不出一个符合上述条件的数的人输。

分析:

既然想不出什么直接搜索之类的方法,那么一定就是找规律了。这题我们来推一下他的条件得到每个人每一步的最利于自己的做法。

考虑三个数:S(i-2),S(i-1),Si,假设当前步骤是生成Si,那么必须满足的条件是S(i-2)<Si<n,又因为Si是由S(i-1)得到的,用上面的公式带入条件不等式有两种情况,我们分开讨论:

1.Si=S(i-1)+dk  

那么对于S(i-1)这个人(设为A)来说,他想让Si(设为B)输,所以A在生成S(i-1)的时候肯定是想构造一个数S(i-1),让B无论怎么选择dk都不能由S(i-1)生成合法的Si。

不合法的Si也就是Si<=S(i-2)并且Si>n,也就是说即使选择最小的dmin也不能满足S(i-1)-dmin>S(i-2)或者S(i-1)+dmin<=n,又因为S(i-1)=S(i-2)+dk,带入得:

S(i-2)+dk-dmin<=S(i-2) 且 S(i-2)+dk+dmin>n,满足这两个条件的dk只能是dmin,所以A在生成S(i-1)的时候为了使B输,他会选择+dmin

2.Si=S(i-1)-dk

推理方法同理,你会发现这个不能在生成自己的时候陷害别人,所以这个不是最利于自己的做法。

综上,每个人每一步都会选择最利于自己的做法是+dmin,之后就模拟一遍,然后谁先>n就谁输。

博弈问题一般解法:根据条件推出每人最利于自己的做法然后:1.模拟一遍得出结果;2.根据数据特征如奇偶性直接判断出结果

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define INF 1000000007
using namespace std;
int t,n,m;
int d;
int main()
{
     scanf("%d",&t);
	 for(int cas=1;cas<=t;cas++){
	 	scanf("%d%d",&n,&m);
	 	int mi=INF;
	 	for(int i=0;i<m;i++){
	 		scanf("%d",&d);
	 		mi=min(mi,d);
	 	}
	    int a=0,b=mi;
	    int ok;
	    if(mi>n) ok=1;
	    else{
		    	while(1){
			    	int tmp=a;
			    	a=b+mi;
			    	b=a+mi;
			    	if(a>n){
			    		ok=0;break;
			    	}
			    	if(b>n){
			    		ok=1;break;
		    	    }
		        }
	    }	    
	    printf("Case #%d: ",cas);
	    if(ok) printf("Alice\n");
	    else printf("Bob\n");
	 }	
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值