容易发现跟树没什么关系,可以预处理出每个点若走向分叉点期望走多少步才能回到上个存档点,就变为链上问题了。考虑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 记忆的轮廓(概率期望+动态规划+决策单调性)的更多相关文章

  1. [BZOJ4899]:记忆的轮廓(概率DP)

    题目传送门 题目描述: 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...

  2. BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】

    Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...

  3. [bzoj4899]记忆的轮廓 题解(毒瘤概率dp)

    题目背景 四次死亡轮回后,昴终于到达了贤者之塔,当代贤者夏乌拉一见到昴就上前抱住了昴“师傅!你终于回来了!你有着和师傅一样的魔女的余香,肯定是师傅”.众所周知,大贤者是嫉妒魔女沙提拉的老公,400年前 ...

  4. Bzoj4899 记忆的轮廓

    B. 记忆的轮廓 题目描述 通往贤者之塔的路上,有许多的危机.我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增,在[1,n]中,一共有n个节点.我 ...

  5. BZOJ1563 NOI2009诗人小G(动态规划+决策单调性)

    设f[i]为前i行的最小不协调度,转移枚举这一行从哪开始,显然有f[i]=min{f[j]+abs(s[i]-s[j]+i-j-1-m)p}.大胆猜想有决策单调性就好了.证明看起来很麻烦,从略.注意需 ...

  6. 【题解】亚瑟王 HNOI 2015 BZOJ 4008 概率 期望 动态规划

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4008 一道不简单的概率和期望dp题 根据期望的线性性质,容易想到,可以算出每张卡的期望伤害, ...

  7. BZOJ5305 HAOI2018苹果树(概率期望+动态规划)

    每种父亲编号小于儿子编号的有标号二叉树的出现概率是相同的,问题相当于求所有n个点的此种树的所有结点两两距离之和. 设f[n]为答案,g[n]为所有此种树所有结点的深度之和,h[n]为此种树的个数. 枚 ...

  8. BZOJ4832 抵制克苏恩(概率期望+动态规划)

    注意到A+B+C很小,容易想到设f[i][A][B][C]为第i次攻击后有A个血量为1.B个血量为2.C个血量为3的期望伤害,倒推暴力转移即可. #include<iostream> #i ...

  9. UOJ#196. 【ZJOI2016】线段树 概率期望,动态规划

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ196.html 题解 先离散化,设离散化后的值域为 $[0,m]$ . 首先把问题转化一下,变成:对于每一个位置 $i$ ...

随机推荐

  1. Android开发——你真的了解Dialog、Toast和Snackbar吗

    0. 前言 今天给大家带来一篇简单易懂的关于Android提醒小功能的文章.Dialog和Toast我们都不陌生,而Snackbar是Design Support库中提供的新控件,有些朋友可能还不了解 ...

  2. JS基础,课堂作业,三个数字排序

    三个数字大小排序 <script> var a = parseInt(prompt("请输入第一个整数:")); var b = parseInt(prompt(&qu ...

  3. Spark实施备忘

    AttributeError: 'SparkConf' object has no attribute '_get_object_id' 初始化SparkContext时出现这种错误是因为把Spark ...

  4. MYSQL主从复制配置(整理)

    MYSQL主从原理及过程 原理 Mysql的 Replication 是一个异步的复制过程(mysql5.1.7以上版本分为异步复制和半同步两种模式),从一个 Mysql instace(我们称之为 ...

  5. 《算法图解》——第十章 K最近邻算法

    第十章    K最近邻算法 1 K最近邻(k-nearest neighbours,KNN)——水果分类 2 创建推荐系统 利用相似的用户相距较近,但如何确定两位用户的相似程度呢? ①特征抽取 对水果 ...

  6. Spring学习(3):Spring架构(转载)

    1. Spring架构图 核心容器:包括Core.Beans.Context.EL模块. ●Core模块:封装了框架依赖的最底层部分,包括资源访问.类型转换及一些常用工具类. ●Beans模块:提供了 ...

  7. 《机器学习实战》6.2小节,KKT条件代码理解

    <机器学习实战>6.2小节 #这句是检测 当前样本点i 是否满足KKT条件的 if (alphas[i, :] < C and E_i * labelMat[i, :] < - ...

  8. 华为笔试——C++的int型数字位排序

    题目:int型数字位排序 题目介绍:输入int 型整数,按照从右至左的顺序,返回不含重复数字的新整数. 例: 输入: 99824270 输出: 072489 分析:乍一看很简单,但是很容易忽略int ...

  9. hbase Problem binding to node1/192.168.1.13:16020 : 地址已在使用

    这是hbase 从0.9.x升级到1.x后HMaster与HRegionServer端口冲突问题 在hbase升级到1.0.0版本后,默认端口做了改动.其中16020端口是hmaster服务和hreg ...

  10. netty初认识

    Netty是什么? 本质:JBoss做的一个Jar包 目的:快速开发高性能.高可靠性的网络服务器和客户端程序 优点:提供异步的.事件驱动的网络应用程序框架和工具 通俗的说:一个好使的处理Socket的 ...