(期望dp)lightoj1030Discovering Gold

lightoj1030Discovering Gold

题意&思路:

n n n个格子,每个格子上有 a i a_i ai个黄金。一个人的起始格子为1,每次投一个六面骰子,得到数字 x x x,如果当前位置为 i i i,且 x + i < = n x+i<=n x+i<=n,就前进x格并捡起黄金,否则再投一次。问到n的格子上时,得到的黄金期望为多少。
因为每个走过的格子一定能拿到黄金,所以 d p [ i ] = a [ i ] dp[i]=a[i] dp[i]=a[i]
由于最后跳到 n n n点是确定的,所以我们可以得到 d p [ n ] = a [ n ] dp[n]=a[n] dp[n]=a[n]
所以我么可以得到:
d p [ n − 1 ] = a [ n − 1 ] + d p [ n ] \begin{aligned}dp[n-1]=a[n-1]+dp[n]\end{aligned} dp[n1]=a[n1]+dp[n]
d p [ n − 2 ] = a [ n − 2 ] + d p [ n ] 2 + d p [ n − 1 ] 2 \begin{aligned}dp[n-2]=a[n-2]+\frac{dp[n]}{2}+\frac{dp[n-1]}{2}\end{aligned} dp[n2]=a[n2]+2dp[n]+2dp[n1]
d p [ n − 3 ] = a [ n − 3 ] + d p [ n ] 3 + d p [ n − 1 ] 3 + d p [ n − 2 ] 3 \begin{aligned}dp[n-3]=a[n-3]+\frac{dp[n]}{3}+\frac{dp[n-1]}{3}+\frac{dp[n-2]}{3}\end{aligned} dp[n3]=a[n3]+3dp[n]+3dp[n1]+3dp[n2]
……
d p [ i ] = a [ i ] + d p [ i + 6 ] 6 + d p [ i + 5 ] 6 + d p [ i + 4 ] 6 + d p [ i + 3 ] 6 + d p [ i + 2 ] 6 + d p [ i + 1 ] 6 \begin{aligned}dp[i]=a[i]+\frac{dp[i+6]}{6}+\frac{dp[i+5]}{6}+\frac{dp[i+4]}{6}+\frac{dp[i+3]}{6}+\frac{dp[i+2]}{6}+\frac{dp[i+1]}{6}\end{aligned} dp[i]=a[i]+6dp[i+6]+6dp[i+5]+6dp[i+4]+6dp[i+3]+6dp[i+2]+6dp[i+1]
……
d p [ 1 ] = a [ 1 ] + d p [ 7 ] 6 + d p [ 6 ] 6 + d p [ 5 ] 6 + d p [ 4 ] 6 + d p [ 3 ] 6 + d p [ 2 ] 6 \begin{aligned}dp[1]=a[1]+\frac{dp[7]}{6}+\frac{dp[6]}{6}+\frac{dp[5]}{6}+\frac{dp[4]}{6}+\frac{dp[3]}{6}+\frac{dp[2]}{6}\end{aligned} dp[1]=a[1]+6dp[7]+6dp[6]+6dp[5]+6dp[4]+6dp[3]+6dp[2]
所以倒着推一遍就行了。

代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<ctype.h>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
const int N=1e6+10;
const int mod=1e7+9;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
int a[110];
double dp[110];
int main()
{
	int t,l;
	scanf("%d",&t);
	for(l=1;l<=t;l++)
	{
		memset(dp,0,sizeof(dp));
		int n,i,j;
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			dp[i]=a[i];
		}
		for(i=n-1;i>=1;i--)
		{
			for(j=1;j<=6;j++)
			{
				int k=min(6,n-i);
				dp[i]+=dp[i+j]/k;
			}
		}
		printf("Case %d: %.7lf\n",l,dp[1]);	
	}
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值