SGU 422 Fast Typing(概率DP)
题目大意
某人在打字机上打一个字符串,给出了他打每个字符出错的概率 q[i]。 打一个字符需要单位1的时间,删除一个字符也需要单位1的时间。在任意时刻,他可以花 t 的时间检查整个打出来的字符串,并且从当前光标删除到第一个出错的位置(留下的字符串要么为空,要么每个字符都是对的)。问你,他正确的打完该字符串最少需要花费的时间的期望值是多少
字符串的长度小于等于3000
题意有点绕,具体可以看看原题是怎么描述的
做法分析
首先确定这是一个概率DP的问题。
定义状态 f[i] 表示正确的打完前 i 个字符以后,最少还需要多少时间正确的打完所有字符
可以这样转移:往后连续打 j 个字符之后再来花时间检查字符串,并且删除,具体的转移方程就是这样的:
对于一个具体的 j :
令 g[i][j]= j+t
+q[i+1]*(f[i]+j) // 在第 i+1 位出错
+p[i+1]*q[i+2]*(f[i+1]+j-1) // 在第 i+2 位出错
+p[i+1]*p[i+2]*q[i+3]*(f[i+2]+j-2) // 在第 i+3 位出错
+......
+p[i+1]*p[i+2]*p[i+3]*...*q[i+j]*(f[i+j-1]+1) // 在第 i+j 位出错
+p[i+1]*p[i+2]*p[i+3]*...*p[i+j]*f[i+j] // 连续打的 k 个字符全部正确
上式中,p[i] 表示第 i 个字符正确的概率,q[i] 表示第 i 个字符错误的概率,p[i]+q[i]=1
考虑到上式需要移项来解出 f[i] 的具体表达式,而移到等式右边的始终是 q[i+1]*f[i],不妨对 g[i][j] 稍作修改
令 g[i][j]= j+t
+q[i+1]*j // 在第 i+1 位出错
+p[i+1]*q[i+2]*(f[i+1]+j-1) // 在第 i+2 位出错
+p[i+1]*p[i+2]*q[i+3]*(f[i+2]+j-2) // 在第 i+3 位出错
+......
+p[i+1]*p[i+2]*p[i+3]*...*q[i+j]*(f[i+j-1]+1) // 在第 i+j 位出错
+p[i+1]*p[i+2]*p[i+3]*...*p[i+j]*f[i+j] // 连续打的 k 个字符全部正确
那么,我们就有:f[i]=min{ g[i][j] }/(1-q[i+1])=min{ g[i][j] }/p[i+1],1≤j≤n-i
初始状态:f[n]=0
目标状态:f[0]
虽然状态转移方程推出来了,但是不要急,注意数据范围:n≤3000
按照上面的式子 DP 的话,这个做法是 n3 的复杂度,还需要做一些优化
我们观察 g[i][j] 和 g[i][j+1] 的关系:
g[i][1]=1+t+q[i+1]+p[i+1]*f[i+1]
g[i][2]=2+t+q[i+1]*2+p[i+1]*q[i+2]*(f[i+1]+1)+p[i+1]*p[i+2]*f[i+2]
=g[i][1]+1+q[i+1]+p[i+1]*p[i+2]*f[i+2]+(p[i+1]*q[i+2]-p[i+1])*f[i+1]+p[i+1]*q[i+2]
=g[i][1]+1+q[i+1]+p[i+1]*q[i+2]+p[i+1]*p[i+2]*f[i+2]-p[i+1]*p[i+2]*f[i+1]
=g[i][1]+1+1-p[i+1]*p[i+2]+p[i+1]*p[i+2]*f[i+2]-p[i+1]*p[i+2]*f[i+1]
=g[i][1]+2+p[i+1]*p[i+2]*(f[i+2]-f[i+1]-1)
同理:g[i][3]=g[i][2]+2+p[i+1]*p[i+2]*p[i+3]*(f[i+3]-f[i+2]-1)
推到这里,规律已经呼之欲出了。运用这个规律,便可以省去一个循环,把 n3 变成 n2
写的那么复杂,其实代码就几行...
非常好的一道题目,赞一个!
参考代码
#include <iostream>
#include <cstring>
#include <cstdio> using namespace std; const int N=; int n, t;
double p[N], f[N]; int main()
{
while(scanf("%d%d", &n, &t)!=EOF)
{
for(int i=; i<=n; i++) scanf("%lf", &p[i]), p[i]=-p[i];
f[n]=;
for(int i=n-; i>=; i--)
{
double cur=t++(-p[i+])+p[i+]*f[i+];
double temp=p[i+];
f[i]=cur;
for(int j=; i+j<=n; j++)
{
temp*=p[i+j];
cur+=-temp+temp*f[i+j]-temp*f[i+j-];
f[i]=min(f[i], cur);
}
f[i]/=p[i+];
}
printf("%.8lf\n", f[]);
}
return ;
}
SGU 422
题目连接 & AC通道
SGU 422 Fast Typing(概率DP)的更多相关文章
- SGU 495 Kids and Prizes:期望dp / 概率dp / 推公式
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495 题意: 有n个礼物盒,m个人. 最开始每个礼物盒中都有一个礼物. m个人依次随 ...
- [转]概率DP总结 by kuangbin
概率类题目一直比较弱,准备把kuangbin大师傅总结的这篇题刷一下! 我把下面的代码换成了自己的代码! 原文地址:http://www.cnblogs.com/kuangbin/archive/20 ...
- Codeforces 866C Gotta Go Fast - 动态规划 - 概率与期望 - 二分答案
You're trying to set the record on your favorite video game. The game consists of N levels, which mu ...
- dice 概率论 概率DP
题目链接: http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1010&cid=459 找出公式,公式有实际意义,某种情形当 ...
- Codeforces 28C [概率DP]
/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队 ...
- HDU 4405 Aeroplane chess (概率DP)
题意:你从0开始,要跳到 n 这个位置,如果当前位置是一个飞行点,那么可以跳过去,要不然就只能掷骰子,问你要掷的次数数学期望,到达或者超过n. 析:概率DP,dp[i] 表示从 i 这个位置到达 n ...
- POJ 2096 Collecting Bugs (概率DP)
题意:给定 n 类bug,和 s 个子系统,每天可以找出一个bug,求找出 n 类型的bug,并且 s 个都至少有一个的期望是多少. 析:应该是一个很简单的概率DP,dp[i][j] 表示已经从 j ...
- POJ 2151 Check the difficulty of problems (概率DP)
题意:ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 ,求每队至少解出一题且冠军队至少解出N道题的概率. 析:概率DP,dp[i][j][k] 表示第 i 个队伍,前 j 个题,解出 ...
- 概率DP light oj 1030
t组数据 n块黄金 到这里就捡起来 出发点1 到n结束 点+位置>n 重掷一次 dp[i] 代表到这里的概率 dp[i]=(dp[i-1]+dp[i-2]... )/6 如果满6个的话 否则 ...
随机推荐
- C# 两行代码实现 延迟加载的单例模式(线程安全)
关键代码第4,5行. 很简单的原理不解释:readonly + Lazy(.Net 4.0 + 的新特性) public class LazySingleton { //Lazy singleton ...
- C++ 面向对象编程
<C++ Primer 4th>读书笔记 面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.在 C++ 中,用类进行数据抽象,用类派生从一个类继承另一个:派生类继承基类的成员.动态绑 ...
- C语言实现冒泡排序-整数排序
我一直觉得排序算法挺重要的,但是却没有深入的去理解它: 没有深入理解就无法用代码将它实现: 在腾讯的在线模拟考试中就有一题问到冒泡排序: 我几乎是傻眼了!我知道这样的问题是最基础的: 无论过去怎样现在 ...
- Singleton模式和Mono-State模式
类和实例 对于大多数的类,都可以创建多个实例.在需要和不需要时,创建和删除这些实例.该过程会伴随着内存的分配和归还. 同时,有一些类,应该仅有一个实例.该实例在程序启动/结束时被创建和删除. root ...
- hdu4508 完全背包,湫湫系列故事——减肥记I
湫湫系列故事——减肥记I 对于01背包和完全背包,昨晚快睡着的时候,突然就来了灵感 区别:dp[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值 在第二重循环,01 是倒着循环的,因 ...
- time
http://blog.csdn.net/JGood/archive/2010/04/07/5457284.aspx Python提供了多个内置模块用于操作日期时间,像calendar,time ...
- python两个文件的对比
#encoding=utf-8 class SyncPagemaptoDB(object): def loadOldmap(self,oldpage,newpage,new_version): map ...
- Cocos2d-x3.x塔防游戏(保卫萝卜)从零开始(一)
一.前提: 完成Hello Game项目的创建编译. 具体参考:Cocos2dx.3x_Hello Game项目创建篇 二.本篇目标: l 说说关于塔防游戏的想法和思路 l 实现一个简单的塔防游戏 ...
- MiniDao-PE精简版
https://github.com/zhangdaiscott/minidao-pe MiniDao-PE精简版 MiniDao-PE 简介及特征 MiniDao-PE 是一种持久化解决方案,类似m ...
- 奇怪吸引子---ShimizuMorioka
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...