动归
这道题题意是有九行四列的字母,对于每一行的首字母,如果和另一行相同那么就可以消掉,如果有n多种选择那么选择某一个的概率就是1/n,问最后全部消掉的概率
我首先的想法是对于第一列的字母,算出可以得组合共有n个,那么选择其中一个的概率就是1/n,然后递归分别进入每一个选择中,继续算,比较麻烦的是标记,假设对于第一个选择,它每走一次,首字母就会变一次。
然后看了大佬的代码。
首先就是不是先算出所有的可能再递归,遇到可以得就递归并计数num,最后再/num就可以了,这样就省事很多
然后标记的时候,大佬用5^9来标记,具体看代码
当所有的字母都标记过后 d[0]=1.0,返回;如果没有全部走完无路可走,返回0
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e6+5,M=1953124;//!
double d[N];
char c[10][5],s[5],vis[N];
double dp(int u) //printf("dp %d\n",u);
{
if(vis[u])
return d[u];
vis[u]=1;
int a[10],cnt=0;
for(int i=1,t=u; i<=9; i++,t/=5)
a[i]=t%5; //,printf("a %d %d\n",t,i,a[i]);
for(int i=1; i<=9; i++)
for(int j=i+1; j<=9; j++)
if(a[i]&&a[j]&&c[i][a[i]]==c[j][a[j]])
{
cnt++;
int t=0;
for(int k=9; k>=1; k--)
{
t*=5;
if(k==i||k==j)
t=t+a[k]-1;
else
t+=a[k];
}
d[u]+=dp(t);
}
if(cnt)
d[u]/=(double)cnt;
return d[u];
}
int main(int argc, const char * argv[])
{
for(int i=1; i<=9; i++)
for(int j=1; j<=4; j++)
{
scanf("%s",s+1);
c[i][j]=s[1];
}
d[0]=1.0;
printf("%.6f",dp(M));
return 0;
}
/*
AS 9S 6C KS
JC QH AC KH
7S QD JD KD
QS TS JS 9H
6D TD AD 8S
QC TH KC 8D
8C 9D TC 7C
9C 7H JH 7D
8H 6S AH 6H
*/
买了两件很漂亮的裙子拍照用,试了一下红色的很适合去废墟中拍那种feel的片子,明天跟着两个大师去拍照,摄影师&模特