首页 > 其他 > 详细

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

时间:2021-06-14 23:36:51      阅读:23      评论:0      收藏:0      [点我收藏+]

题目链接

题意:

题目大意: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;
}

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

原文:https://www.cnblogs.com/KingZhang/p/14883214.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!