这个有环的情况非常的讨厌,一开始想通过数学推等比数列的和,但是发现比较繁就不做了。

然后挖掘这题性质。

  • 数据比较小,但是体力可以很接近1(恼怒),也就是说可能可以跳很多很多步。算了一下,大概跳了2e7次左右这个体力才缩到1e-14左右,这时已经几乎不会影响答案惹。也就是说,点比较少,有没有暴力做法?
  • 发现从一个点假设满体力开始跳若干步,有最大价值的方案,如果前面一个点跳若干步过来,再在这个点以某个$x∈(0,1)$的体力开始,那么原来的最大的方案还是最大的,只要乘上一开始这个体力就好了。这说明答案可以用类似dp的方式逼近。

然后看这个跳非常多步还可以dp就反应到了倍增跳跃的模型。设$f[i][j][k]$为从$i$到$j$跳$2^k$步最大价值。然后可以倍增推了。

$f[i][j][k]=\max \{ f[i][l][k-1] + p^{2^{k-1}}*f[l][j][k-1] \} $

这个是$O(n^3 logn)$的,log那个是自己调的,25左右为宜。

由于是个人想的,所以实现上比较清奇。后来看了说本质就是个floyd。。感觉我理解还不够深入呃,如果谁知道为什么换一下枚举顺序就可以滚动了,烦请赐教。

另外有一个坑暂时不知道为什么,line34初始化要先给没有自环的连上自环,价值0。以后可能会请教别人这个地方,在座各位如果知道为什么这样还望不吝赐教。。


2019.9.29 UPD:从神仙hkk处获取了为什么要给所有点都连自环$0$:如果是下面这组数据:


 0.5

hack!!

显然有问题。因为,这里的路是有尽头的,需要跳三步,而没办法有一个状态有效表示跳3步,不妨改变状态设计,设$f[i][j][k]$为从$i$到$j$跳最多$2^k$步最大价值。然后$f_{1,4,2}$就可以表示这个答案,而原来答案是没法表示的,但又因而引出这个$2^2$步的最后一步没办法再跳的问题,也就是在$4$号点没路了。这时候如果按照原来的dp方法,转移$f_{1,4,2}=f_{1,3,1}+p^2f_{3,4,1}$,但是这里的$f_{3,4,1}$按照新定义是可以有值的,如果直接用之前dp方程dp,会因为$f_{3,4,1}$没有值而出错,原因在于$f_{3,4,1}$最大时是$3\to 4$跳$2^0$步,满足新的定义,但是没法保留到$f_{3,4,1}$,这要求我们手动给$3$或者$4$添加一个0的自环保证可以按新定义正常转移。这样,就不会出现$2$的整数次方跳不完,后半截没有值而出错的情况。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<bitset>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=;
db f[N][N][];
db fp[],A[N],p,ans;
int n,m,s;
inline db fpow(db x,int k){db ret=;for(;k;k>>=,x*=x)if(k&)ret*=x;return ret;} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n),read(m);
for(register int k=;k<=;++k)
for(register int i=;i<=n;f[i][i][k]=,++i)
for(register int j=;j<=n;++j)
f[i][j][k]=-0x3f3f3f3f;
for(register int i=;i<=n;++i)scanf("%lf",&A[i]);
read(s);scanf("%lf",&p);
for(register int i=;i<=;++i)fp[i]=fpow(p,<<i);
for(register int i=,x,y;i<=m;++i)read(x),read(y),f[x][y][]=A[y]*p;
for(register int k=;k<=;++k)
for(register int i=;i<=n;++i)
for(register int l=;l<=n;++l)
for(register int j=;j<=n;++j)
MAX(f[i][j][k],f[i][l][k-]+fp[k-]*f[l][j][k-]);
for(register int j=;j<=n;++j)MAX(ans,f[s][j][]);
ans+=A[s];printf("%.1lf\n",ans);
return ;
}

BZOJ2306 [Ctsc2011]幸福路径[倍增]的更多相关文章

  1. BZOJ2306:[CTSC2011]幸福路径(倍增Floyd)

    Description 有向图 G有n个顶点 1,  2, …,  n,点i 的权值为 w(i).现在有一只蚂蚁,从给定的起点 v0出发,沿着图 G 的边爬行.开始时,它的体力为 1.每爬过一条边,它 ...

  2. bzoj2306 [Ctsc2011]幸福路径 倍增 Floyd

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2306 题解 倍增 Floyd. 令 \(f[i][j][k]\) 表示走了 \(2^i\) 步 ...

  3. 【bzoj2306】[Ctsc2011]幸福路径 倍增Floyd

    题目描述 一张n个点的有向图,每个点有一个权值.一开始从点$v_0$出发沿图中的边任意移动,移动到路径上的第$i$个点 输入 每一行中两个数之间用一个空格隔开. 输入文件第一行包含两个正整数 n,  ...

  4. BZOJ2306: [Ctsc2011]幸福路径

    Description 有向图 G有n个顶点 1, 2, -, n,点i 的权值为 w(i).现在有一只蚂蚁,从 给定的起点 v0出发,沿着图 G 的边爬行.开始时,它的体力为 1.每爬过一条 边,它 ...

  5. 【BZOJ2306】幸福路径(动态规划,倍增)

    [BZOJ2306]幸福路径(动态规划,倍增) 题面 BZOJ 题解 不要求确切的值,只需要逼近 显然可以通过移动\(\infty\)步来达到逼近的效果 考虑每次的一步怎么移动 设\(f[i][j]\ ...

  6. 【BZOJ 2306】 2306: [Ctsc2011]幸福路径 (倍增floyd)

    2306: [Ctsc2011]幸福路径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 912  Solved: 437 Description 有向 ...

  7. [CTSC2011]幸福路径

    题目描述 有向图 G有n个顶点 1, 2, …, n,点i 的权值为 w(i).现在有一只蚂蚁,从 给定的起点 v0出发,沿着图 G 的边爬行.开始时,它的体力为 1.每爬过一条 边,它的体力都会下降 ...

  8. BZOJ 2306: [Ctsc2011]幸福路径

    Description 有向图 G有n个顶点 1, 2, -, n,点i 的权值为 w(i).现在有一只蚂蚁,从 给定的起点 v0出发,沿着图 G 的边爬行.开始时,它的体力为 1.每爬过一条 边,它 ...

  9. 「CTSC 2011」幸福路径

    [「CTSC 2011」幸福路径 蚂蚁是可以无限走下去的,但是题目对于精度是有限定的,只要满足精度就行了. \({(1-1e-6)}^{2^{25}}=2.6e-15\) 考虑使用倍增的思想. 定义\ ...

随机推荐

  1. Bug解决:mysql 创建表字段Double类型长度

    excel导入数据进行新增时,发现安装高度和可视距离在数据库创建都是double类型 程序跑完,执行成功后,数据库的数据是2,小数点后的数据没有了 打印sql并执行后发现sql并没有错误, 检查数据库 ...

  2. RedisTemplate5种数据结构操作

    1 操作字符串 redisTemplate.opsForValue(); 2 操作hash redisTemplate.opsForHash(); 3 操作list redisTemplate.ops ...

  3. 【HANA系列】SAP HANA SQL条件判断是NULL的写法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL条件判断 ...

  4. SQLServer2008R2复制发布订阅(含局域网跨网段)调试总结

    需要注意的问题点: 一.发布服务器A和订阅服务器B都在同一个网段的局域网内 1.两台服务器的SQLServer版本必须一致. 2.两服务器之间访问没难度,直接就可以搜索到. 3.注意请求订阅和推送订阅 ...

  5. 给Date的构造函数添加属性和方法

    let d = Date.prototype; Object.defineProperties(d, { 'year': { get: function () { return this.getFul ...

  6. 使用PowerShell 自动创建DFS复制组

    运行环境:Windows Server 2012 R2 DFS 复制概述  DFS复制组 PowerShell脚本命令 需要注意的是DFS依赖域,若此服务器未存在于域控上,或未存在域内,则此脚本会报错 ...

  7. mysql的root密码忘了

    忘记密码:https://www.cnblogs.com/ryanzheng/p/9348723.htmlmy.cnf的[mysqld]下加:skip-grant-tables重启 mysql -ur ...

  8. PTA(Basic Level)1046.划拳

    划拳是古老中国酒文化的一个有趣的组成部分.酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字.如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输家罚一杯酒.两人同赢或两人同输 ...

  9. NumPy进阶

    数组算术 任何两个等尺寸数组之间的算术操作都应用了逐元素操作的方式. arr1 = np.array([[1,2,3],[4,5,6]]) arr2 = np.array([[4,2,1],[7,2, ...

  10. @Transactional spring事务回滚相关

    还可以设置回滚点,看下面 /** * 用户登录接口 * * * 1明确事务方法前的命名规则 * 2保证事务方法执行的时间尽可能的短,不允许出现循环操作,不允许出现RPC等网络请求操作 * 3不允许所有 ...