CTSC2011 幸福路径
Posted excellent-zzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CTSC2011 幸福路径相关的知识,希望对你有一定的参考价值。
传送门 https://www.luogu.org/problemnew/show/P4308
给定一张有向图,每个点有个权值,蚂蚁从某个点开始,初始体力为1,每经过一条边,体力会变为原来的p(0 < p < 1)倍,每爬到一个点,获得的幸福度为该点的权值乘上体力。求蚂蚁幸福度的最大值,保留一位小数。
这道题最开始拿到的时候想到用期望dp,然后自己推出了一个式子,感觉没什么问题,交上去之后发现只得了40分,然鹅不造哪里错了。最后看到大佬们都用FLOYD做的。
考虑到体力是按指数级衰减的,所以我们只要做下面的一个dp就可以解决问题了。
令f[t][i][j]表示走2t步,从i走到j获得的最大幸福度。
f[t][i][j] = max(f[t - 1][i][k] + f[t - 1][k][j] * p2t - 1)
当t足够大时,f得到的就近似为最大幸福度,或者说当p < eps 时,得到的就近似为最大幸福度。
#define B cout << "BreakPoint" << endl; #define O(x) cout << #x << " " << x << endl; #define O_(x) cout << #x << " " << x << " "; #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl; #include <cstdio> #include <cstring> #include <algorithm> #define N 110 using namespace std; int n,m,s; double p,ans,v[N],f[N][N],dp[N][N]; void read1(){ scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) scanf("%lf",&v[i]); scanf("%d",&s); scanf("%lf",&p); return ; } void read2(){ while(m--) { int u,x; scanf("%d%d",&u,&x); f[u][x] = v[x] * p; } } void init(){ for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i != j) f[i][j] = -1e100; return ; } void solve(){ for(; p > 1e-10; p *= p) { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) dp[i][j] = -1e100; for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) dp[i][j] = max(dp[i][j],f[i][k]+f[k][j]*p); memcpy(f,dp,sizeof(dp)); } return ; } void print(){ for(int i = 1; i <= n; i++) ans = max(ans,f[s][i]); printf("%.1f ",ans + v[s]); return ; } int main() { read1(); init(); read2(); solve(); print(); return 0; }
以上是关于CTSC2011 幸福路径的主要内容,如果未能解决你的问题,请参考以下文章