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