[HDOJ 3708][Vjudge 41282] Warrior Lady [动态规划]

69 篇文章 0 订阅
26 篇文章 0 订阅

已知孙尚香具有技能枭姬,当她替换掉现有的装备牌时会新摸两张牌,装备共有4种,现在已知她的手牌情况和牌堆里的牌的情况,初始状态下孙尚香的装备区没有牌,问孙尚香从牌堆里抽取的牌的数量的期望。假设从牌堆里抽取到任意一张牌是等概率的,孙尚香会立刻装备摸到的装备牌。

数据范围:所有的牌的总数不会超过104

动态规划,定义状态dp[i][j][k],i表示装备区状态,范围从0到15,记录4种装备都有没有,j表示牌堆里还有的现在已经装备了该种装备的牌数,k表示牌堆里的其他牌的牌数。dp[i][j][k]表示在此状态下,我们还能额外抽到的牌的期望。

我们可以根据这3个值,计算出是否还有摸牌机会。

状态转移方程:每次摸牌有概率摸到已经有的装备牌(会增加两次摸牌机会),没有的装备牌(改变装备去状态),其他牌(仅消耗了一次摸牌机会)。

#include <cstdio>
#include <cstring>

double dp[16][105][105];
int visited[16][105][105];
int initChance,cas,initState,initI,initJ;
int initDeck[5];

int calChance(int s,int i,int j) {
	int ans=initChance+i+j-initI-initJ;
	int k,initSum=0;
	for (k=0;k<4;k++) {
		if ((s&1<<k)!=0) {
			initSum+=initDeck[k];
			if ((initState&1<<k)==0) initSum--;
		}
	}
	ans+=(initSum-i)*2;
	return ans;
}

double cal(int s,int i,int j) {
	if (i<0||j<0) return 0;
	if (i==0&&j==0) return 0;
	if (visited[s][i][j]==cas) return dp[s][i][j];
	if (calChance(s,i,j)>0) {
		dp[s][i][j]=1+(double)i/(i+j)*cal(s,i-1,j);
		int k,l=j;
		for (k=0;k<4;k++) {
			if ((s&1<<k)==0) {
				l-=initDeck[k];
				dp[s][i][j]+=(double)initDeck[k]/(i+j)*cal(s|1<<k,i+initDeck[k]-1,j-initDeck[k]);
			}
		}
		dp[s][i][j]+=(double)l/(i+j)*cal(s,i,j-1);
	} else dp[s][i][j]=0;
	//printf("%d %d %d: %d %lf\n",s,i,j,calChance(s,i,j),dp[s][i][j]);
	visited[s][i][j]=cas;
	return dp[s][i][j];
}

int main() {
	int t,i,j,x;
	scanf("%d",&t);
	memset(visited,0,sizeof(visited));
	for (cas=1;cas<=t;cas++) {
		initChance=0;
		initState=0;
		for (i=0;i<4;i++) {
			scanf("%d",&x);
			if (x>0) initState|=1<<i;
			if (x>1) initChance+=(x-1)*2;
		}
		scanf("%d",&x);
		initI=initJ=0;
		for (i=0;i<5;i++) {
			scanf("%d",&initDeck[i]);
			if (i<4&&(initState&1<<i)!=0) initI+=initDeck[i];
			else initJ+=initDeck[i];
		}
		printf("Case %d: %.2lf\n",cas,cal(initState,initI,initJ));
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值