P1837 单人纸牌 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)(逐渐变懒)
(这是我写过最壮观的dp)
这个题其实不难,但是设计状态需要一定的胆量(?
我们设计dp[a][b][c][d][e][f][g][h][i]表示九叠牌分别被取走abcdefghi张时的概率
再开一个sz[i][j]数组用来存第i叠的第j个数字(注意牌的输入顺序是从下往上)
然后就直接暴力转移,(注意在转移之前要先跑一遍一共有多少对牌可以取,记录在sum里,因为George是等概率取,所以到达下面每一个状态的概率是现在的概率*1/sum)
然后就没有了……(这是个设计状态需要勇气但写起来一点都不难的dp)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; char s[1005]; char sz[10][5]; double ans,dp[5][5][5][5][5][5][5][5][5],a; long long i[10],shu; int main(){ for(int i=1;i<=9;i++){ gets(s); sz[i][1]=s[9]; sz[i][2]=s[6]; sz[i][3]=s[3]; sz[i][4]=s[0]; } dp[0][0][0][0][0][0][0][0][0]=1; for(i[1]=0;i[1]<=4;i[1]++){ for(i[2]=0;i[2]<=4;i[2]++){ for(i[3]=0;i[3]<=4;i[3]++){ for(i[4]=0;i[4]<=4;i[4]++){ for(i[5]=0;i[5]<=4;i[5]++){ for(i[6]=0;i[6]<=4;i[6]++){ for(i[7]=0;i[7]<=4;i[7]++){ for(i[8]=0;i[8]<=4;i[8]++){ for(i[9]=0;i[9]<=4;i[9]++){ if(dp[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]]!=0){ a=dp[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]]; shu=0; for(int x=1;x<=9;x++){ for(int y=x+1;y<=9;y++){ if(i[x]+1<=4&&i[y]+1<=4&&sz[x][i[x]+1]==sz[y][i[y]+1]){ shu++; } } } if(shu!=0){ for(int x=1;x<=9;x++){ for(int y=x+1;y<=9;y++){ if(i[x]+1<=4&&i[y]+1<=4&&sz[x][i[x]+1]==sz[y][i[y]+1]){ i[x]++; i[y]++; dp[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]]+=a/(double)(shu*1.0); i[x]--; i[y]--; } } } } } } } } } } } } } } printf("%.6lf ",dp[4][4][4][4][4][4][4][4][4]); return 0; }