P4308 [CTSC2011]幸福路径
第一眼瞄上去似乎很不可做,那么我们考虑直接放弃当 \(P\) 不停地乘一个小于1的常数那么就无限趋近0而 \(w_i \le 100\) 而且只保留一位小数。
那么我们爆搜不停滚动DP就完了。注意初始值一定要赋负无穷(很大很大就可以哦,0是不能油库里的)。
方程:
\(f_{k, i, j} = \max(f_{k, i,j}, f_{k-1, i, l} + f_{k-1, l, j} * \rho * 2^k)\)
\(k\) 是滚动的那一维,然后直接 \(P = P * P\) 就行了。
复杂度不会算
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MAXN = 1e2+10;
const double ep = 1e-10;
ll S, N, M;
double val[MAXN], f1[MAXN][MAXN], f2[MAXN][MAXN], P;
int main() {
scanf("%lld%lld", &N, &M);
for (ll i = 1; i <= N; i++) scanf("%lf", val+i);
scanf("%lld", &S);
scanf("%lf", &P);
for (ll i = 1; i <= N; i++) for (ll j = 1; j <= N; j++) if (i != j) f1[i][j] = -1e10;
for (ll i = 1, x, y; i <= M; i++) {
scanf("%lld%lld", &x, &y);
f1[x][y] = val[y] * P;
}
for (; P >= ep; P *= P) {
for (ll i = 1; i <= N; i++) for (ll j = 1; j <= N; j++) f2[i][j] = -1e10;
for (ll k = 1; k <= N; k++) {
for (ll i = 1; i <= N; i++) {
for (ll j = 1; j <= N; j++) {
f2[i][j] = max(f2[i][j], f1[i][k] + f1[k][j] * P);
}
}
}
swap(f1, f2);
}
double ans = -1e10;
for (ll i = 1; i <= N; i++) {
ans = max(ans, f1[S][i]);
}
printf("%.1f", ans + val[S]);
return 0;
}
希望我们都有一个光明的未来