2019.03.06【BJOI2018】【洛谷P4459】双人猜数游戏(DP)

传送门


解析:

直接用 f [ i ] [ j ] [ t ] f[i][j][t] f[i][j][t]表示 i , j i,j i,j在第 t t t轮能否被确定。DP转移后贪心选择最小的答案就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define cs const

cs int N=305;
int s,t;
bool f[N][N][20];
string name;
bool flag;

inline bool Check_Alice(int x,int y,int t){
	int num=x*y,lim=sqrt(num),xx=0,cnt=0;
	for(int re i=s;i<=lim;++i){
		if(num%i==0){
			if(!t||!f[i][num/i][t-1]){
				xx=i;
				if(1<++cnt)return false;
			}
		}
	}
	return xx==x;
}

inline bool Check_Bob(int x,int y,int t){
	int num=x+y,lim=num/2,xx=0,cnt=0;
	for(int re i=s;i<=lim;++i){
		if(!t||!f[i][num-i][t-1]){
			xx=i;
			if(1<++cnt)return false;
		}
	}
	return xx==x;
}

inline bool Check_Alice_end(int x,int y){
	int num=x*y,lim=sqrt(num),xx=0,cnt=0;
	for(int re i=s;i<=lim;++i){
		if(num%i==0){
			if((t<2||!f[i][num/i][t-2])&&f[i][num/i][t]){
				xx=i;
				if(1<++cnt)return false;
			}
		}
	}
	return xx==x;
}

inline bool Check_Bob_end(int x,int y){
	int num=x+y,lim=num/2,xx=0,cnt=0;
	for(int re i=s;i<=lim;++i){
		if((t<2||!f[i][num-i][t-2])&&f[i][num-i][t]){
			xx=i;
			if(1<++cnt)return false;
		}
	}
	return xx==x;
}

signed main(){
//	freopen("guess.in","r",stdin);
//	freopen("guess.out","w",stdout);
	cin>>s>>name>>t;
	if(name=="Alice")flag=true;
	for(int re tt=0;tt<=t;++tt,flag=!flag)
	for(int re i=s;i<=300;++i)
	for(int re j=s;j<=300;++j){
		if(tt>=2)f[i][j][tt]=f[i][j][tt-2];
		if(!f[i][j][tt])
		if(flag)f[i][j][tt]=Check_Alice(i,j,tt);
		else f[i][j][tt]=Check_Bob(i,j,tt);
	}
	for(int re sum=s*2;;++sum){
		for(int re i=s,j;i<=sum/2;++i){
			j=sum-i;
			if(!f[i][j][t])continue;
			flag=true;
			for(int re k=0;k<t;++k){
				if(f[i][j][k]){
					flag=false;
					break;
				}
			}
			if(!flag)continue;
			if((t&1)==(name=="Alice"))flag=Check_Alice_end(i,j);
			else flag=Check_Bob_end(i,j);
			if(flag){
				cout<<i<<" "<<j<<"\n";
				return 0;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值