P1220 关路灯 简单dp题 70分求助
查看原帖
P1220 关路灯 简单dp题 70分求助
303673
waadwdwqdqwd楼主2020/9/10 11:51

题解都说用sum[i][j] 表示 除去i到j 的功率的剩下的攻率和 然后每次更新就加上就行了

这不是逆的推的么? 然后我就觉得正的推应该也行 就用F[i][j][i]表示 关闭 ij 的然后结束位置是 i 的时间(这个时间是在最少功率的基础上的) 然后用f[i][j][i] 表示dp的那个东东 然后就只有70分吖 为啥啊 感觉应该一样吧..

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 55;
ll f[maxn][maxn][maxn];
ll F[maxn][maxn][maxn];
ll rote[maxn], wi[maxn];
ll lu(int a, int b) {
	return abs(rote[a] - rote[b]);
}
int main() {
	int n, c;
	cin >> n >> c;
	for (int i = 1; i <= n; i++) {
		scanf("%lld%lld", rote + i, wi + i);
	}
	memset(f, 0x3f, sizeof(f));
	f[c][c][c] = 0;
	// F 不需要初始化 因为如果当前的没有遍历过那么 f 就已经是最大的了 
	for (int len = 1; len <= n; len++) {
		for (int i = c - len + 1; i <= c; i++) {
			int l = max(1, i), r = min(i + len - 1, n);// l表示区间左端点, r 为右端点
			if (f[l][r][l] > f[l + 1][r][r] + (lu(r, l) + F[l + 1][r][r]) * wi[l]) {
				f[l][r][l] = f[l + 1][r][r] + (lu(r, l) + F[l + 1][r][r]) * wi[l];
				F[l][r][l] = lu(r, l) + F[l + 1][r][r];
			}
			if (f[l][r][l] > f[l + 1][r][l + 1] + (lu(l + 1, l) + F[l + 1][r][l + 1]) * wi[l]) {
				f[l][r][l] = f[l + 1][r][l + 1] + (lu(l + 1, l) + F[l + 1][r][l + 1]) * wi[l];
				F[l][r][l] = lu(l + 1, l) + F[l + 1][r][l + 1];
			} 	
			if (f[l][r][r] > f[l][r - 1][r - 1] + (lu(r - 1, r) + F[l][r - 1][r - 1]) * wi[r]) {
				f[l][r][r] = f[l][r - 1][r - 1] + (lu(r - 1, r) + F[l][r - 1][r - 1]) * wi[r];
				F[l][r][r] = lu(r - 1, r) + F[l][r - 1][r - 1];
			} 
			if (f[l][r][r] > f[l][r - 1][l] + (lu(l, r) + F[l][r - 1][l]) * wi[r]) {
				f[l][r][r] = f[l][r - 1][l] + (lu(l, r) + F[l][r - 1][l]) * wi[r];
				F[l][r][r] = lu(l, r) + F[l][r - 1][l];
			} 
		}
	} 
	cout << min(f[1][n][1], f[1][n][n]) << endl;
	return 0;
}
2020/9/10 11:51
加载中...