BZOJ4899 记忆的轮廓(概率期望+动态规划+决策单调性)
容易发现跟树没什么关系,可以预处理出每个点若走向分叉点期望走多少步才能回到上个存档点,就变为链上问题了。考虑dp,显然有f[i][j]表示在i~n中设置了j个存档点,其中i设置存档点的最优期望步数。转移枚举下一个存档点设在哪,则有f[i][j]=min(f[k][j-1]+d[i][k]),其中d[i][k]为从i号点存档点走到k号存档点其间没有别的存档点的期望步数。对d数组可以把一堆方程列出来手动加减消元得到式子,n2就可以求出。这样复杂度O(Tn3)。于是直接暴力就在darkbzoj上水过了。或者加一些乱七八糟的剪枝就能跑得飞快。然后有感性理解比较显然的一点是这个东西有决策单调性,于是就能做到O(Tn2logn)。证明估计得列一堆式子不太敢证了。然而由于d数组已经大到爆了精度,需要一些乱七八糟的处理,本来还以为是决策单调性写挂了调了半天一点卵用都没有。尽管这样还是没在bzoj上过掉,不知道bzoj有什么奇怪的精度问题。被恶心死了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 710
#define inf 1000000000
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,m,k,p[N<<],L[N],R[N],id[N],top,t;
double v[N<<],d[N][N],f[N][N],son[N<<];
struct data{int to,nxt;
}edge[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k)
{
for (int i=p[k];i;i=edge[i].nxt)
{
son[k]++;
dfs(edge[i].to);
v[k]+=v[edge[i].to]+;
}
if (son[k]) v[k]/=son[k];
son[k]++;
}
double calc(int i,int x,int y){return f[i-][y]+d[x][y];}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4899.in","r",stdin);
freopen("bzoj4899.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
n=read(),m=read(),k=read();
memset(p,,sizeof(p));t=;
memset(son,,sizeof(son));
memset(v,,sizeof(v));
for (int i=;i<=m-n;i++)
{
int x=read(),y=read();
addedge(x,y);
}
for (int i=;i<=n;i++) dfs(i),v[i]++;
for (int i=;i<n;i++)
{
double t=;
for (int j=i;j<n;j++)
{
d[i][j+]=d[i][j]+t/son[j]+t*(son[j]-)/son[j]*v[j];
t/=son[j];
}
t=;double s=;
for (int j=i;j<n;j++)
{
s-=t*(son[j]-)/son[j];
d[i][j+]/=s;
t/=son[j];
}
}
for (int i=;i<n;i++) f[][i]=inf;
for (int i=;i<=n;i++)
for (int j=i+;j<=n;j++)
if (d[i][j]>inf) d[i][j]=1ll*inf*(j+);
for (int i=;i<=k;i++)
{
top=;id[]=n;L[]=,R[]=n-;
for (int j=n-;j>=;j--)
{
int l=,r=top,x=;
while (l<=r)
{
int mid=l+r>>;
if (L[mid]<=j&&R[mid]>=j) {x=mid;break;}
else if (L[mid]>j) l=mid+;
else r=mid-;
}
f[i][j]=calc(i,j,id[x]);
while (top&&R[top]<j&&calc(i,R[top],j)<calc(i,R[top],id[top])) top--;
l=L[top],r=min(j,R[top])-,x=L[top]-;
/*for (int p=r;p>=l;p--)
if (calc(i,p,j)<calc(i,p,id[top])) {x=p;break;}*/
while (l<=r)
{
int mid=l+r>>;
if (calc(i,mid,j)<calc(i,mid,id[top])) x=mid,l=mid+;
else r=mid-;
}
L[top]=x+;
if (x) top++,id[top]=j,L[top]=,R[top]=x;
}
}
/*for (int i=2;i<=k;i++)
for (int j=n-1;j>=1;j--)
{
f[i][j]=inf;
for (int x=j+1;x<=min(j+7+n/k,n);x++)
f[i][j]=min(f[i][j],calc(i,j,x));
}*/
printf("%.4f\n",f[k][]);
}
return ;
}
BZOJ4899 记忆的轮廓(概率期望+动态规划+决策单调性)的更多相关文章
- [BZOJ4899]:记忆的轮廓(概率DP)
题目传送门 题目描述: 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
- BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】
Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
- [bzoj4899]记忆的轮廓 题解(毒瘤概率dp)
题目背景 四次死亡轮回后,昴终于到达了贤者之塔,当代贤者夏乌拉一见到昴就上前抱住了昴“师傅!你终于回来了!你有着和师傅一样的魔女的余香,肯定是师傅”.众所周知,大贤者是嫉妒魔女沙提拉的老公,400年前 ...
- Bzoj4899 记忆的轮廓
B. 记忆的轮廓 题目描述 通往贤者之塔的路上,有许多的危机.我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增,在[1,n]中,一共有n个节点.我 ...
- BZOJ1563 NOI2009诗人小G(动态规划+决策单调性)
设f[i]为前i行的最小不协调度,转移枚举这一行从哪开始,显然有f[i]=min{f[j]+abs(s[i]-s[j]+i-j-1-m)p}.大胆猜想有决策单调性就好了.证明看起来很麻烦,从略.注意需 ...
- 【题解】亚瑟王 HNOI 2015 BZOJ 4008 概率 期望 动态规划
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4008 一道不简单的概率和期望dp题 根据期望的线性性质,容易想到,可以算出每张卡的期望伤害, ...
- BZOJ5305 HAOI2018苹果树(概率期望+动态规划)
每种父亲编号小于儿子编号的有标号二叉树的出现概率是相同的,问题相当于求所有n个点的此种树的所有结点两两距离之和. 设f[n]为答案,g[n]为所有此种树所有结点的深度之和,h[n]为此种树的个数. 枚 ...
- BZOJ4832 抵制克苏恩(概率期望+动态规划)
注意到A+B+C很小,容易想到设f[i][A][B][C]为第i次攻击后有A个血量为1.B个血量为2.C个血量为3的期望伤害,倒推暴力转移即可. #include<iostream> #i ...
- UOJ#196. 【ZJOI2016】线段树 概率期望,动态规划
原文链接www.cnblogs.com/zhouzhendong/p/UOJ196.html 题解 先离散化,设离散化后的值域为 $[0,m]$ . 首先把问题转化一下,变成:对于每一个位置 $i$ ...
随机推荐
- 3.MUI端APP获取Json数据,并且实现遍历
在MUI中,对JSON的操作还是非常方便的. <script type="text/javascript"> var responseEl = document.get ...
- 人脸识别引擎SeetaFaceEngine中Identification模块使用的测试代码
人脸识别引擎SeetaFaceEngine中Identification模块用于比较两幅人脸图像的相似度,以下是测试代码: int test_recognize() { const std::stri ...
- Maven学习(一)-----Maven安装配置总结
想要安装 Apache Maven 在Windows 系统上, 需要下载 Maven 的 zip 文件,并将其解压到你想安装的目录,并配置 Windows 环境变量. 所需工具 : JDK 1.8 M ...
- python全栈开发-面向对象-进阶2
python_day_19 今日主要内容: 1.抽象类,接口类 2.多态 3.封装 1.抽象类,接口类 python 没有接口这个概念接口类,抽象类: 制定一个规范. 举个栗子:你的项目经理提一个需求 ...
- itchat个人练习 语音与文本图灵测试例程
背景介绍 itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单. 使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人. 官方文档参考https://itchat ...
- python学习-linux基本操作
1.sudo 管理员root身份 2.mkdir 创建文件夹 touch 创建文件 3.rm 删除 4.chmod 赋予权限 r(读取):4 w(写):2 x(执行):1 rwx=7,r-x=5等 ...
- Mac下布置appium环境
1.下载或者更新Homebrew:homebrew官网 macOS 不可或缺的套件管理器 $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githu ...
- TW实习日记:第六天
今日的一整天都是在开发微信相关的接口,因为项目的系统是嵌在企业微信中,所以不可避免的要产生微信UserID和企业系统ID的匹配关系,那么就需要用手机号或是邮箱这种两边都存在的唯一参数进行匹配.然后再将 ...
- Python中如何实现im2col和col2im函数(sliding类型)
今天来说说im2col和col2im函数,这是MATLAB中两个内置函数,经常用于数字图像处理中.其中im2col函数在<MATLAB中的im2col函数>一文中已经进行了简单的介绍. 一 ...
- Atom 插件 Sync Settings 备份与恢复
当使用 Atom IDEA.随着使用的越来越多,安装的插件也越来越多,一旦电脑重装后需要复原开发环境,这将是一件比较头疼的事.「Sync Settings」插件可以帮助我们解决这个问题. 操作流程 安 ...