您的位置:首页 > 其它

运用记忆化搜解决的概率期望问题

2012-10-07 11:42 197 查看
这个算是脱了很久很久的一片解题报告了。主要是运用动态规划求解期望问题的解法,一般用记忆化搜的写法更好理解。以几个题为例:

UVALive 5811,Card。
题意很简单:一副扑克牌共有13张黑桃,红心,梅花,方片和大小王各一张,input会给出黑桃,红心,梅花,方片的数量。问从随机分布的一堆牌中依次抽取一张牌,达到题中所要求的数量,至少需要抽取牌的期望,如果抽到大小王,则可以把它们当成任意花色,因为要求抽取的牌数最少,所以当然是当成最需要的了。
比赛训练时想了很久,都没有想出来,最后还是看了大牛的代码才略懂一二。主要是用dp值表示期望,记忆化搜直接出解,dp[a][b][c][d][big][small]表示抽取了a张黑桃,b张红心,c张梅花,d张方片,大小王分别当成了big和small(为4表示还没有用过大小王,0表示黑桃,1表示红心,2表示梅花,3表示方片),其他的看代码就知道了

View Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 105;
const int inf = (1<<30);
const double gold = (1+sqrt(5.0))/2;
int c[maxn], n, d[maxn];
double dp[maxn][10005];
double ans;
int cal(int c){
return int(gold*c*c);
}
double dfs(int deep, int f){
int i, j;
if(dp[deep][f]>-0.5){
return dp[deep][f];
}
double tmp = 0.0;
for(i=1;i<=n;i++){
if(f>c[i]){
tmp += (deep+(double)d[i])/n;
}
else{
tmp += dfs(deep+1,min(f+c[i],10001))/n;
}
}
return dp[deep][f] = tmp;
}
int main(){
int f, i, j, k, l;
while(~scanf("%d%d",&n,&f)){
for(i=1;i<=n;i++){
scanf("%d",&c[i]);
d[i] = cal(c[i]);
}
for(i=0;i<maxn;i++){
for(j=0;j<10005;j++){
dp[i][j] = -1.0;
}
}
c[0] = 0;
printf("%.3lf\n",dfs(0,f));
}
return 0;
}


还有一些用记忆化搜不好求解的题目,也就是直接求解就好了的题~~,比如 URAL - 1776 Anniversary Firework,UVALive - 5721 Activation(这个求递推公式很奇葩,算做数学题一样~)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: