[bzoj2037][Sdoi2008]Sue的小球

题目链接

算是一道比较明显的区间$dp$,但是状态不同往常。

$dp[0/1][i][j]$为拿完第$i$个和第$j$个范围内的所有球后停在左边/右边的最小亏损。

$dp[0][i][j] = min(dp[0][i][j], min(dp[0][i + 1][j] +亏损, dp[1][i + 1][j] + 亏损))$

$dp[1][i][j] = min(dp[1][i][j], min(dp[1][i][j - 1] + 亏损, dp[0][i][j - 1] +亏损))$

亏损的计算方式为速度的区间和*距离

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1000 + 10;
 5 struct node {
 6     int x, y, v;
 7 }a[maxn];
 8 bool cmp(node a, node b) {
 9     return a.x < b.x;
10 }
11 int dp[2][maxn][maxn], c[maxn];
12 int qi(int l, int r) {
13     return c[r] - c[l - 1];
14 }
15 int main() {
16     int n, q;
17     int sum = 0;
18     memset(dp, 0x3f, sizeof(dp));
19     scanf("%d%d", &n, &q);
20     for (int i = 1; i <= n; i++)
21         scanf("%d", &a[i].x);
22     for (int i = 1; i <= n; i++)
23         scanf("%d", &a[i].y), sum += a[i].y;
24     for (int i = 1; i <= n; i++)
25         scanf("%d", &a[i].v);
26     a[++n] = { q,0,0 };
27     sort(a + 1, a + 1 + n, cmp);
28     for (int i = 1; i <= n; i++)
29         c[i] = c[i - 1] + a[i].v;
30     for (int i = 1; i <= n; i++)
31         if (a[i].x == q && a[i].v == 0)
32             dp[0][i][i] = dp[1][i][i] = 0;
33     for (int k = 2; k <= n; k++) {
34         for (int i = 1; i + k - 1 <= n; i++) {
35             int j = i + k - 1;
36             dp[0][i][j] = min(dp[0][i][j], min(dp[0][i + 1][j] + (qi(1, i) + qi(j + 1, n)) * (a[i + 1].x - a[i].x), dp[1][i + 1][j] + (qi(1, i) + qi(j + 1, n)) * (a[j].x - a[i].x)));
37             dp[1][i][j] = min(dp[1][i][j], min(dp[1][i][j - 1] + (qi(1, i - 1) + qi(j, n)) * (a[j].x - a[j - 1].x), dp[0][i][j - 1] + (qi(1, i - 1) + qi(j, n)) * (a[j].x - a[i].x)));
38         }
39     }
40     printf("%.3f
", (sum - min(dp[0][1][n], dp[1][1][n])) / 1000.0);
41 }

原文地址:https://www.cnblogs.com/sainsist/p/11800486.html