P4308 [CTSC2011]幸福路径

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;
}
posted @ 2020-09-14 16:53  Gensokyo_Alice  阅读(73)  评论(0编辑  收藏  举报