洛谷__P1220 关路灯(区间DP)
题目链接:P1220 关路灯 - 洛谷
题目大意:
有 n 盏路灯,位置递增,每盏灯有位置和功率。
老张从第 c 盏灯出发,以 1 m/s 速度移动,关灯时间忽略,没关的灯会持续耗电(焦耳 = 瓦 × 秒),
求:关掉所有灯的最小总耗电量。
思路:
观察到,最后一个关的灯一定是在最左边或是最右边(总不能大老远跑过去关灯连经过的灯也不关吧),
从 c 点出发,最优解一定是反复地往左或往右关掉距离自己最近的灯;
这里考虑区间dp,
f[L][R][0]为关掉区间 [L , R] 的灯后位于区间左端位置,即: L
f[L][R][1]为关掉区间 [L , R] 的灯后位于区间右端位置,即: R
在这讨论f[L][R][0]这种情况:
关掉区间 [L , R] 灯后位于L,那可以是从f[L+1][R][0],即从 L+1 走到 L,也可以是f[L+1][R][1],即从 R 走到 L
耗电情况用前缀和维护,
记录下每个状态下的最优解;
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 51, mod = 998244353;
int n, c;
int t[N], w[N], s[N];
int f[N][N][2];
void solve() {
cin >> n >> c;
for (int i = 1; i <= n; i++) {
cin >> t[i] >> w[i];
s[i] = s[i - 1] + w[i];
}
mst(f, 1);
f[c][c][0] = f[c][c][1] = 0;
for (int len = 2; len <= n; len++) {//区间长度
for (int l = 1; l + len - 1 <= n; l++) {//枚举左端点,同时右端点不超过n
int r = l + len - 1;//右端点
f[l][r][0] = min(f[l + 1][r][0] + (t[l + 1] - t[l]) * (s[l] + s[n] - s[r]),
f[l + 1][r][1] + (t[r] - t[l]) * (s[l] + s[n] - s[r]));
f[l][r][1] = min(f[l][r - 1][0] + (t[r] - t[l]) * (s[l - 1] + s[n] - s[r - 1]),
f[l][r - 1][1] + (t[r] - t[r - 1]) * (s[l - 1] + s[n] - s[r - 1]));
}
}
cout << min(f[1][n][0], f[1][n][1]);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号