洛谷 P1837 单人纸牌

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;
}

  

原文地址:https://www.cnblogs.com/lichangjian/p/15123959.html