P1220 关路灯

P1220 关路灯

区间 \(DP\) , 设 \(f[i][j][0/1]\) 表示关完 \([i, j]\) 的灯后在左/右边的最小值, 然后我们枚举 \(i\)\(j\) , 用 \(f[i][j][0/1]\) 更新状态 \(f[i - 1][j][0/1]\)\(f[i][j + 1][0/1]\) .

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 55;
int n, c, pos[N], cost[N], sum[N], f[N][N][2];
int main () {
    n = read(), c = read();
    memset(f, 0x3f, sizeof(f)); f[c][c][1] = f[c][c][0] = 0;
    for (int i = 1; i <= n; i++) {
        pos[i] = read(), cost[i] = read();
        sum[i] = sum[i - 1] + cost[i];
    }
    for (int i = c; i >= 1; i--) {
        for (int j = c; j <= n; j++) {
            int cost1 = sum[n] - sum[j] + sum[i - 1];
            if (i > 1) {
                f[i - 1][j][0] = min(f[i][j][0] + (pos[i] - pos[i - 1]) * cost1, f[i][j][1] + (pos[j] - pos[i - 1]) * cost1);
                f[i - 1][j][1] = min(f[i - 1][j][1], f[i - 1][j][0] + (pos[j] - pos[i - 1]) * (cost1 - cost[i - 1]));
            }
            if (j < n) {
                f[i][j + 1][1] = min(f[i][j][1] + (pos[j + 1] - pos[j]) * cost1, f[i][j][0] + (pos[j + 1] - pos[i]) * cost1);
                f[i][j + 1][0] = min(f[i][j + 1][0], f[i][j + 1][1] + (pos[j + 1] - pos[i]) * (cost1 - cost[j + 1]));
            }
        }
    }
    printf("%d", min(f[1][n][0], f[1][n][1]));
    return 0;
}

一定要初始化...因为没初始化卡了好久...

posted @ 2021-08-23 10:57  sshadows  阅读(26)  评论(0编辑  收藏  举报