用九元组表示当前状态,即每队牌剩的张数,状态总数为5^9=1953125.
设d[ i ]表示状态i对应的成功概率,则根据全概率公式,d[ i ]为后继成功概率的平均值,按照动态规划的写法计算即可。
这个动态规划我不会写,帅哥思路真的很清晰很好啊。
但是学会还是很高兴的
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
vector<char> v[9];
double d[5][5][5][5][5][5][5][5][5];
int vis[5][5][5][5][5][5][5][5][5];
double dp(int t0,int t1,int t2,int t3,int t4,int t5,int t6,int t7,int t8)
{
double& ans=d[t0][t1][t2][t3][t4][t5][t6][t7][t8];
if(vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]) return ans;
vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]=1;
int te[9]={t0,t1,t2,t3,t4,t5,t6,t7,t8};
int ok=1;
for(int i=0;i<9;i++) if(te[i]){ok=0; break;}
if(ok) return ans=1;
ans=0;
int num=0;
double pum=0;
for(int i=0;i<9;i++) if(te[i])
for(int j=i+1;j<9;j++) if(te[j]&&v[i][te[i]-1]==v[j][te[j]-1])
{
num++;
te[i]--; te[j]--;
pum+=dp(te[0],te[1],te[2],te[3],te[4],te[5],te[6],te[7],te[8]);
te[i]++; te[j]++;
}
if(num==0) return ans=0;
else return ans = pum/(num*1.0);
}
int main()
{
char s[5];
while(scanf("%s",s)!=EOF)
{
mem(d);
mem(vis);
for(int i=0;i<9;i++)
v[i].clear();
v[0].push_back(s[0]);
for(int i=1;i<=3;i++)
{
scanf("%s",s);
v[0].push_back(s[0]);
}
for(int i=1;i<9;i++)
{
for(int j=1;j<=4;j++)
{
scanf("%s",s);
v[i].push_back(s[0]);
}
}
printf("%lf\n",dp(4,4,4,4,4,4,4,4,4));
}
return 0;
}
定义状态的方法和状态转移的方法都很好,要学习。
方法值得常思考常学习~