那么进一步为:\(f(i,j,0/1)\),分别表示关完区间\(i,j\)等时,关灯人处于左端点或者右端点的最小消耗。
最后\(ans=min(f(1,n,1),f(1,n,0))\),因为不知道最后关灯人在左边最优还是右边最优。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 60;
int n, c, ans;
int p[maxn], v[maxn], sum[maxn];
int f[maxn][maxn][3];
int main()
{
scanf("%d%d", &n, &c);
for(int i = 1; i <= n; i++)
scanf("%d%d", &p[i], &v[i]);
for(int i = 1; i <= n; i++)
sum[i] = sum[i-1] + v[i];
memset(f, 0x3f, sizeof f);
f[c][c][0] = f[c][c][1] = 0;
for(int len = 2; len <= n; len++)
for(int l = 1; l <= n - len + 1; l++)
{
int r = len + l - 1;
f[l][r][0] = min(f[l+1][r][0]+(p[l+1]-p[l])*(sum[l]+sum[n]-sum[r]), f[l+1][r][1]+(p[r]-p[l])*(sum[l]+sum[n]-sum[r]));
f[l][r][1] = min(f[l][r-1][0]+(p[r]-p[l])*(sum[l-1]+sum[n]-sum[r-1]), f[l][r-1][1]+(p[r]-p[r-1])*(sum[l-1]+sum[n]-sum[r-1]));
} cout << min(f[1][n][0], f[1][n][1]) << endl;
return 0;
}
原文:https://www.cnblogs.com/zxytxdy/p/12056978.html