题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3329

题意:

  给你面数分别为k1,k2,k3的三个骰子。

  给定a,b,c三个整数。

  三个骰子每扔一次,若骰子朝上的点数分别为a,b,c,则分数清零,否则当前分数+=骰子点数之和。

  当分数 > n时游戏结束。

  问你扔骰子次数的期望。

题意:

  表示状态:

    dp[i] = rest steps

    (当前分数为i时,剩余步数的期望)

  找出答案:

    ans = dp[0]

    刚开始分数为0。

  如何转移:

    由于此题中可以由高分数转移到低分数,所以转移存在环。

    一般有环dp用高斯消元做。

    但是,此题的所有环都跟dp[0]有关,也就是说所有的转移都能写成形如 dp[i] = a[i]*dp[0] + b[i] 的形式(分离系数)。

    那么求出a[0]和b[0]就可以行了,答案为dp[0] = b[0] / (1-a[0])。

    (1)dp[i] = sigma(dp[i+k]*p[k]) + dp[0]*p[0] + 1 (原转移方程,p[i]为扔出点数为i的概率,p[0]为扔出(a,b,c)的概率)

    (2)dp[i] = a[i]*dp[0] + b[i] (假设的)

    将(2)代入(1):

      dp[i] = sigma( (a[i+k]*dp[0] + b[i+k]) * p[k] ) + dp[0]*p[0] + 1

      dp[i] = sigma( a[i+k]*dp[0]*p[k] + b[i+k]*p[k] ) + dp[0]*p[0] + 1

      dp[i] = ( sigma(a[i+k]*p[k]) + p[0] )*dp[0] + sigma(b[i+k]*p[k]) + 1

    系数对应相等:

      a[i] = sigma(a[i+k]*p[k]) + p[0]

      b[i] = sigma(b[i+k]*p[k]) + 1

    递推求出a[i] & b[i]即可,求的时候要保证i <= n(有意义)。

    dp[0] = b[0] / (1-a[0])。

AC Code:

 // state expression:
// dp[i] = rest steps
// i: present score
//
// find the answer:
// ans = dp[0]
//
// transferring:
// 1) dp[i] = sigma(dp[i+k]*p[k]) + dp[0]*p[0] + 1
// 2) dp[i] = a[i]*dp[0] + b[i]
// ***solve:
// dp[i] = sigma( (a[i+k]*dp[0] + b[i+k]) * p[k] ) + dp[0]*p[0] + 1
// dp[i] = sigma( a[i+k]*dp[0]*p[k] + b[i+k]*p[k] ) + dp[0]*p[0] + 1
// dp[i] = ( sigma(a[i+k]*p[k]) + p[0] )*dp[0] + sigma(b[i+k]*p[k]) + 1
// ***result:
// a[i] = sigma(a[i+k]*p[k]) + p[0]
// b[i] = sigma(b[i+k]*p[k]) + 1
// ***run:
// cal a[i] & b[i]
// dp[0] = b[0] / (1-a[0])
//
// boundary:
// set a,b = 0
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 505
#define MAX_K 40 using namespace std; int n,t;
int k1,k2,k3;
int e1,e2,e3;
double p[MAX_K];
double a[MAX_N];
double b[MAX_N];
double dp[MAX_N]; void read()
{
cin>>n>>k1>>k2>>k3>>e1>>e2>>e3;
} void cal_pro()
{
memset(p,,sizeof(p));
p[]=1.0/(k1*k2*k3);
for(int i=;i<=k1;i++)
{
for(int j=;j<=k2;j++)
{
for(int k=;k<=k3;k++)
{
if(i!=e1 || j!=e2 || k!=e3)
{
p[i+j+k]+=p[];
}
}
}
}
} void cal_const()
{
memset(a,,sizeof(a));
memset(b,,sizeof(b));
for(int i=n;i>=;i--)
{
for(int k=;k<=k1+k2+k3;k++)
{
if(i+k>n) break;
a[i]+=a[i+k]*p[k];
b[i]+=b[i+k]*p[k];
}
a[i]+=p[];
b[i]+=1.0;
}
} void solve()
{
cal_pro();
cal_const();
dp[]=b[]/(1.0-a[]);
} void print()
{
printf("%.15f\n",dp[]);
} int main()
{
cin>>t;
while(t--)
{
read();
solve();
print();
}
}

ZOJ 3329 One Person Game:期望dp【关于一个点成环——分离系数】的更多相关文章

  1. ZOJ 3329 Problem Set (期望dp)

    One Person Game There is a very simple and interesting one-person game. You have 3 dice, namely Die1 ...

  2. ZOJ 3329 One Person Game 概率DP 期望 难度:2

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3754 本题分数为0的概率不确定,所以不能从0这端出发. 设E[i]为到达成功所 ...

  3. zoj 3329 One Person Game 概率DP

    思路:这题的递推方程有点麻烦!! dp[i]表示分数为i的期望步数,p[k]表示得分为k的概率,p0表示回到0的概率: dp[i]=Σ(p[k]*dp[i+k])+dp[0]*p0+1 设dp[i]= ...

  4. poj 2096 Collecting Bugs && ZOJ 3329 One Person Game && hdu 4035 Maze——期望DP

    poj 2096 题目:http://poj.org/problem?id=2096 f[ i ][ j ] 表示收集了 i 个 n 的那个. j 个 s 的那个的期望步数. #include< ...

  5. poj 2096 , zoj 3329 , hdu 4035 —— 期望DP

    题目:http://poj.org/problem?id=2096 题目好长...意思就是每次出现 x 和 y,问期望几次 x 集齐 n 种,y 集齐 s 种: 所以设 f[i][j] 表示已经有几种 ...

  6. ZOJ 3822 Domination 期望dp

    Domination Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem ...

  7. 成环的概率dp(初级) zoj 3329

    原题地址:https://vjudge.net/problem/ZOJ-3329 题目大意: 有三个骰子,分别有k1,k2,k3个面,初始分数是0.第i骰子上的分数从1道ki.当掷三个骰子的点数分别为 ...

  8. 【BZOJ-1419】Red is good 概率期望DP

    1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Di ...

  9. [NOIP2016]换教室 D1 T3 Floyed+期望DP

    [NOIP2016]换教室 D1 T3 Description 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 ...

随机推荐

  1. greenDAO学习分享总结

    greenDAO(最新版本号V2.0.0的Readme) ======== greenDAO is a light & fast ORM solution for Android that m ...

  2. vue install 注册组件

    1.myPlugin.js文件 let MyPlugin = {}; MyPlugin.install = function (Vue, options) { // 1. 添加全局方法或属性 Vue. ...

  3. Android日期对话框NumberPicker的使用方法教程

    NumberPicker是Android3.0之后引入的一个控件.NumberPicker 是用于选择一组提前定义好数字的控件.比方时间hour的选择仅仅有0-23有效,则能够通过setMinValu ...

  4. oracle 使用job定时自动重置sequence

    一.赋予用户创建和删除sequence的权限 grant create any sequence to user_name; grant drop any sequnce to user_name; ...

  5. mysql经常使用查询:group by,左连接,子查询,having where

    前几天去了两个比較牛的互联网公司面试.在sql这块都遇到问题了,哎.可惜呀,先把简单的梳理一下 成绩表 score 1.group by 使用 按某一个维度进行分组 比如: 求每一个同学的总分 SEL ...

  6. 解决opencv无法读AVI视频的问题

    原文来自:http://blog.csdn.net/yeqiu712/article/details/6220030 其实AVI只是一个外壳.里面的东西可不一样的! 问题:为什么我的电脑支持AVI或者 ...

  7. OpenCV 中的三大数据类型( 概述 )

    前言 OpenCV 提供了许多封装好了的类型,而其中,以三大类型最为核心.本文将大致介绍这三大类型. CvArr:不确定数组 它可以被视为一个抽象基类,后面的两大类型都继承此类型并扩展.只要某个函数的 ...

  8. 在另一个线程中无法用((CMainFrame *)AfxGetMainWnd())

    一个vc6的项目放到vc8下重新编译这里死活过不去 查了些资料无果后来翻到一句老外的回答 If AfxGetMainWnd is called from the application’s prima ...

  9. Android - 使用messager实现进程间通信(服务器端→客户端,客户端→服务器端双向)

    之前看了一篇,然后不自己动手肯定是不行的,然后自己又写了一遍. 背景: 一般使用messenger进行进程间通信的时候,我们只能进行单方向通信.但是有没有办法让服务器端和客户端进行双向通信呢? 解决思 ...

  10. 【BZOJ2989】数列 kd-tree

    [BZOJ2989]数列 Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...