Dice Possibility hihoCoder第174周

来源:互联网 发布:待机时间长的平板知乎 编辑:程序博客网 时间:2024/06/08 18:06

题意: 求用 N 个色子投出点数和为 M 的概率。

思路: 一开始用 dfs 交了一个答案,得了六十分。观察 dfs 的过程我们能看到有许多重复计算,也能看到很多子问题,比如求N==3,M==11,会利用到N==2,M==10的结果,所以可以采用记忆化搜索,或者直接就是DP做。

代码:
记忆化搜索:

#include<cstdio>#include<cstring>#include<cstdlib>#include<stack>#include<queue>#include<utility>#include<vector>#include<cmath>#include<set>#include<map>#include<iostream>#include<algorithm>#include<sstream>using namespace std;typedef long long LL;int N, M;double f[110][610];double Dfs(int n, int m){    if(f[n][m] != 0) return f[n][m];    if(n == 1) return f[n][m] = 1.0/6;    for(int i=1; i<=6&&m-i>=n-1; i++){        if(m-i > (n-1)*6) continue;        f[n][m] += 1.0/6*Dfs(n-1, m-i);    }    return f[n][m];}int main(){    while(scanf("%d%d", &N, &M) == 2){        printf("%.2lf\n", 100*Dfs(N, M));    }    return 0;}

动态规划:

#include<cstdio>#include<cstring>#include<cstdlib>#include<stack>#include<queue>#include<utility>#include<vector>#include<cmath>#include<set>#include<map>#include<iostream>#include<algorithm>#include<sstream>using namespace std;typedef long long LL;int N, M;double f[110][610];int main(){    memset(f, 0, sizeof(f));    for(int i=1; i<=100; i++){        for(int j=i; j<=i*6; j++){            if(i == 1) f[i][j] = 1.0/6;            else{                for(int k=1; k<=6&&j-k>=i-1; k++){                    f[i][j] += f[1][k]*f[i-1][j-k];                }            }        }    }    while(scanf("%d%d", &N, &M) == 2){        printf("%.2lf\n", 100*f[N][M]);    }    return 0;}
原创粉丝点击