CodeForces 553E Kyoya and Train 动态规划 多项式 FFT 分治
原文链接http://www.cnblogs.com/zhouzhendong/p/8847145.html
题目传送门 - CodeForces 553E
题意
一个有$n$个节点$m$条边的有向图,每条边连接了$a_i$和$b_i$,花费为$c_i$。
每次经过某一条边就要花费该边的$c_i$。
第$i$条边耗时为$j$的概率为$p_{i,j}$。
现在你从$1$开始走到$n$,如果你在$t$单位时间内(包括$t$)到了$n$,不需要任何额外花费,否则你要额外花费$x$。
问你在最优策略下的期望花费最小为多少。
(注意你每走一步都会根据当前情况制定最好的下一步)
$$n\leq 50 ,m \leq 100, t\leq 20000, x\leq 10^6$$
题解
毛爷爷论文题。
放上毛爷爷题解。

我稍微加了点修改。
于是我是不是不用写题解了??
写一下我做这题的感受。
首先自己想了好久yy出了一个倍增+$FFT$,复杂度和标算一样(当然好像是错的),然后觉得过不去。
然后看标算看到分治,没往下看,继续自己yy,好像会了$2只log$,觉得很神奇,因为两只$log$过不去嘛,所以肯定有神奇的优化。
想了很久还是不会,往下一看真的是两只$log$。QAQ。
写代码也是难受,看着标算还是写了50分钟。
关键是还写挂了。
找了好久好久,猛然间发现我在$FFT$之前的给$A$、$B$数组赋值的时候,两次都赋给了$A$,难怪$FFT$结果一直是$0$,然后一边心态爆炸的吐槽,一边交了一发,还好$1A$了,不然心态更爆炸。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=55,M=105,T=20005,S=1<<15;
double PI=acos(-1.0);
int n,m,t,punish;
int a[M],b[M],c[M],dis[N][N];
double dp[N][T],sum[M][T],p[M][T];
int s,d,Rev[S];
struct C{
double r,i;
C(){}
C(double a,double b){r=a,i=b;}
C operator + (C x){return C(r+x.r,i+x.i);}
C operator - (C x){return C(r-x.r,i-x.i);}
C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
}w[S],A[S],B[S];
void FFT(C a[],int n){
for (int i=0;i<n;i++)
if (i<Rev[i])
swap(a[i],a[Rev[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
void solve(int L,int R){
if (L==R){
for (int e=1;e<=m;e++)
dp[a[e]][L]=min(dp[a[e]][L],sum[e][L]+c[e]);
return;
}
int mid=(L+R)>>1;
solve(mid+1,R);
//sum[e][L...mid]+=dp[mid+1...R]#p[e][1...R-L]
//sum[e][L...mid]+=dp[mid+1...R]*p[e][R-L-1...0]
for (s=1,d=0;s<R-mid+R-L;s<<=1,d++);
for (int i=0;i<s;i++){
Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(d-1));
w[i]=C(cos(2*i*PI/s),sin(2*i*PI/s));
}
for (int e=1;e<=m;e++){
for (int i=0;i<s;i++)
A[i]=B[i]=C(0,0);
for (int i=mid+1;i<=R;i++)
A[i-mid-1]=C(dp[b[e]][i],0);
for (int i=1;i<=R-L;i++)
B[R-L-i]=C(p[e][i],0);
FFT(A,s),FFT(B,s);
for (int i=0;i<s;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,s);
for (int i=0;i<s;i++)
A[i].r/=s,w[i].i*=-1.0;
for (int i=L;i<=mid;i++)
sum[e][i]+=A[i-mid-1+(R-L)].r;
}
solve(L,mid);
}
int main(){
scanf("%d%d%d%d",&n,&m,&t,&punish);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
dis[i][j]=i==j?0:1e9;
for (int i=1;i<=m;i++){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
dis[a[i]][b[i]]=min(dis[a[i]][b[i]],c[i]);
for (int j=1;j<=t;j++)
scanf("%lf",&p[i][j]),p[i][j]/=100000;
}
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for (int i=0;i<N;i++)
for (int j=0;j<T;j++)
dp[i][j]=1e9;
for (int i=1;i<=n;i++)
dp[i][t+1]=punish+dis[i][n];
for (int i=0;i<=t;i++)
dp[n][i]=0;
memset(sum,0,sizeof sum);
for (int e=1;e<=m;e++){
double P=0;
for (int i=1;i<=t;i++){
P+=p[e][t-i+1];
sum[e][i]+=P*dp[b[e]][t+1];
}
}
solve(0,t);
printf("%.8lf",dp[1][0]);
return 0;
}
CodeForces 553E Kyoya and Train 动态规划 多项式 FFT 分治的更多相关文章
- [Codeforces 553E]Kyoya and Train(期望DP+Floyd+分治FFT)
[Codeforces 553E]Kyoya and Train(期望DP+Floyd+分治FFT) 题面 给出一个\(n\)个点\(m\)条边的有向图(可能有环),走每条边需要支付一个价格\(c_i ...
- ●codeforces 553E Kyoya and Train
题链: http://codeforces.com/problemset/problem/623/E 题解: FFT,DP 题意: 一个有向图,给出每条边的起点u,终点v,费用c,以及花费每种时间的概 ...
- Codeforces 553E Kyoya and Train
题目大意 链接:CF533E 给一张\(n\)个点,\(m\)条边的图,起点\(1\)终点\(n\),如果不能在\(T\)的时间内到达则需支付\(X\)的代价. 走每条边都会支付一定代价,经过一条边\ ...
- 【CF553E】Kyoya and Train 最短路+cdq分治+FFT
[CF553E]Kyoya and Train 题意:有一张$n$个点到$m$条边的有向图,经过第i条边要花$c_i$元钱,经过第i条边有$p_{i,k}$的概率要耗时k分钟.你想从1走到n,但是如果 ...
- CF 553E Kyoya and Train
题目分析 期望\(\text{dp}\). 设\(f_{i,j}\)表示在第\(j\)个时刻从\(i\)点出发,到达终点的期望花费. 有转移方程: \[ f_{x,t}=\min_{(x,y)\in ...
- 【codeforces 553E】 Kyoya and Train
http://codeforces.com/problemset/problem/553/E (题目链接) 艹尼玛,CF还卡劳资常数w(゚Д゚)w!!系统complex被卡TLE了T_T,劳资写了一天 ...
- 【BZOJ】3456: 城市规划 动态规划+多项式求逆
[题意]求n个点的带标号无向连通图个数 mod 1004535809.n<=130000. [算法]动态规划+多项式求逆 [题解]设$g_n$表示n个点的无向图个数,那么显然 $$g_n=2^{ ...
- Codeforces A. Kyoya and Colored Balls(分步组合)
题目描述: Kyoya and Colored Balls time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- CF553E Kyoya and Train
Kyoya and Train 一个有\(n\)个节点\(m\)条边的有向图,每条边连接了\(a_i\)和\(b_i\),花费为\(c_i\). 每次经过某一条边就要花费该边的\(c_i\). 第\( ...
随机推荐
- 一分钟学会JavaMail(假)__手动滑稽
因为公司内部办公系统(OA)需要增加一个发送邮件的功能,所以学习了这个感觉比较冷门的JavaMail 1.先上成功截图 : 2.准备事项:Java Mail虽然是官方写的,但是没有集成到jdk里面 ...
- 安利一个刚考过的信息安全认证Security+
在目前的信息安全大潮之下,人才是信息安全发展的关键.而目前国内的信息安全人才是非常匮乏的,拥有国际信息安全认证的人才,在未来职业发展.升职加薪的道路上必将优于普通的信息安全从业者. 果哥今天推荐201 ...
- Hbase G1 gc 调优最终参数
export HBASE_HEAPSIZE=16384export HBASE_OFFHEAPSIZE=25gexport HBASE_MASTER_OPTS="$HBASE_MASTER_ ...
- CMDB服务器管理系统【s5day90】:API构造可插拔式插件逻辑
1.服务器端目录结构: 1.__init__.py from django.conf import settings from repository import models import impo ...
- EF CodeFirst系列(2)---CodeFirst的数据库初始化
1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...
- C#开发Windows服务详细流程
1.Windows服务简单介绍 Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应用程序,主要用于长时间运行的功能或者执行定时任务.一般情况下,用户不能通过用户界面来安装和启 ...
- 我是怎么知道 PTHREAD_MUTEX_INITIALIZER 是什么鬼东西的 ??
很简单 写这么几句代码 1 #include <pthread.h> 2 3 PTHREAD_MUTEX_INITIALIZER cpp 一解析就出来了 1714 # 238 " ...
- C++中数组作为形参进行传递(转)
有两种传递方法,一种是function(int a[]); 另一种是function(int *a) 这两种两种方法在函数中对数组参数的修改都会影响到实参本身的值! 对于第一种,根据之前所学,形参是实 ...
- [简洁]JavaScript中添加、移除、移动、复制、创建和查找节点元素
查找: document.getElementsByTagName通过标签名获取元素,不论有多少个都返回元素集合. document.getElementsByClassName通过类名获取元素,同上 ...
- (一)校园信息通微信小程序从前端到后台整和笔记
前段时间接触了微信小程序,现在回过头来做一些笔记. 先上效果图 后台数据管理界面(PHP) 校园信息通微信小程序前端界面 下面先简单的说一下怎样部署一个微信小程序 首先是前端 微信小程序有它专门的开发 ...