紫书-第10章Double Patience(概率+dp)

题目链接

题意:

题目大意:36张牌分成9堆,每堆4张牌,你每次可以任取两堆顶部的牌,但这两张牌点数必须相同。求把所有的牌都拿走的概率。

思路:

可以用dfs的方法模拟抽牌过程。我们定义状态为“每堆牌剩余数量的集合”,由于重复状态较多,而且总状态数较少(\(5^9\)),所以可以用dp的思想,记忆化搜索。

  • 为什么是5那?
  • 因为每一堆都有5种状态,分别是堆中还有多少中牌(0,1,2,3,4)所以是5种.

我们可以用5进制来记录某种状态:

  • 怎么又是5进制?
  • 因为每堆有5种状态,这样用5进制表示是唯一的.

这个地方我们只需要记录第一个字符即可,所以第二个字符不用要%*c是输入字符但是忽略字符 ---奇怪的知识又增加了.
因为我们是多组输入所以:scanf()也有返回值 成功输入是1, 不在输入就退出呗.----奇怪的知识又又增加了.

double ans[maxn];
char a[10][5];
int d[9];
double solve()
{
	int x=0;
	for(int i=0;i<9;i++){
		x=x*5+d[i];///shuomingyizhongzhuangtai
	}
	if(ans[x]>=0){
		return ans[x];
	}
	int cnt=0;double sum=0;
	for(int i=0;i<9;i++){
		for(int j=i+1;j<9;j++){
			if(d[i]&&d[j]&&a[i][d[i]]==a[j][d[j]]){
				d[i]--;d[j]--;
				sum+=solve();
				d[i]++;d[j]++;
				cnt++;
			}
		}
	}
	return ans[x]=cnt?sum*1.0/cnt:0;
}
int main()
{
    ll t = 1;
    ///scanf("%lld",&t);
    while(t)
    {
    	fill(ans,ans+maxn,-1);
        fill(d,d+9,4);
        ans[0]=1;
        for(int i=0; i<9; ++i){
            for(int j=1; j<=4; ++j)
                if(scanf(" %c%*c",&a[i][j])!=1)
                    return 0;                
        }
        printf("%f\n",solve());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值