luoguP2466 [SDOI2008]Sue的小球

此题与\(luoguP1220\)关路灯类似,但是这个题目的收益随时间的变化而变化.

起初我思考来一个三维\(dp\),即两维坐标,一维时间.

可惜爆了空间(艹).

但是由于时间是线性的,所以我们可以反着设.

即设\(dp[0/1][st][ed]\)表示处理完按坐标排序后的第\(st\)个蛋到第\(ed\)个蛋被处理完后对于剩下的蛋所产生的影响.

答案即为\(\sum^{n}_{i=1}y[i]-\min(dp[0][1][n],dp[1][1][n])\).

转移即为普通的区间\(dp\)套路.

\[\begin{align} dp[0][st][ed]=&min(dp[0][st][ed],min(\\&dp[0][st+1][ed]+(sum[n]+sum[st]-sum[ed])*(a[st + 1].x - a[st].x),\\&dp[1][st + 1][ed] + (sum[n] + sum[st] - sum[ed]) * (a[ed].x - a[st].x)));\\ dp[1][st][ed]=&min(dp[1][st][ed],min(\\&dp[1][st][ed - 1] + (sum[n] + sum[st - 1] - sum[ed - 1]) * (a[ed].x - a[ed - 1].x),\\&dp[0][st][ed - 1] + (sum[n] + sum[st - 1] - sum[ed - 1]) * (a[ed].x - a[st].x))); \end{align} \]

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
const int O = 1010;
template<class TT>
il TT read() {
	TT o = 0,fl = 1; char ch = getchar();
	while (!isdigit(ch) && ch != '-') ch = getchar();
	if (ch == '-') fl = -1, ch = getchar();
	while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
	return fl * o;
}
struct Data {
	int x, y, v;
	il bool operator < (Data rhs) const {
		return x < rhs.x;
	}
}a[O];
int n, St, sum[O], dp[2][O][O], Sum;
int main() {
	memset(dp, 63, sizeof dp);
	n = gi() + 1, a[1].x = St = gi();
	for (int i = 2; i <= n; ++i) a[i].x = gi();
	for (int i = 2; i <= n; ++i) a[i].y = gi(), Sum += a[i].y;
	for (int i = 2; i <= n; ++i) a[i].v = gi();
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i].v;
	for (int i = 1; i <= n; ++i)
		if (!a[i].v && a[i].x == St) {
			dp[0][i][i] = dp[1][i][i] = 0;
			break;
		}
	for (int len = 1; len < n; ++len)
		for (int st = 1; st + len <= n; ++st) {
			int ed = st + len;
			dp[0][st][ed] = min(dp[0][st][ed], min(dp[0][st + 1][ed] + (sum[n] + sum[st] - sum[ed]) * (a[st + 1].x - a[st].x), dp[1][st + 1][ed] + (sum[n] + sum[st] - sum[ed]) * (a[ed].x - a[st].x)));
			dp[1][st][ed] = min(dp[1][st][ed], min(dp[1][st][ed - 1] + (sum[n] + sum[st - 1] - sum[ed - 1]) * (a[ed].x - a[ed - 1].x), dp[0][st][ed - 1] + (sum[n] + sum[st - 1] - sum[ed - 1]) * (a[ed].x - a[st].x)));
		}
	printf("%.3lf\n", (Sum - min(dp[1][1][n], dp[0][1][n])) / 1000.);
	return 0;
}
posted @ 2019-10-21 20:20  wuhan2005  阅读(95)  评论(0编辑  收藏  举报