区间DP
题目
题解
$$ i : f[i][j][1] = min (f[i + 1][j][0] + (wt + w[i]) * lt, f[i + 1][j][1] + (wt + w[i]) * (p[i + 1] - p[i])) $$
$$ j : f[i][j][0] = min (f[i][j - 1][0] + (wt + w[j]) * (p[j] - p[j - 1]), f[i][j - 1][1] + (wt + w[j]) * lt); $$
Code
//
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <string>
#include <stdio.h>
#include <climits>
#include <stack>
#include <vector>
// #include <bits/stdc++.h> //万能头
#define INF 0x3f3f3f3f
#define INT_INF 0x3f3f3f3f
#define LONGLONG_INF 0x3f3f3f3f3f3f3f3f
#define DOUBLE_INF 1E5 + 3;
#define ios\
ios::sync_with_stdio(false); \
cin.tie(nullptr); \
cout.tie(nullptr)
#define TE true
#define FA false
#define fi first
#define se second
#define be begin
#define en end
#define FOR(k, lll, rrr) for (long long i = (lll); i <= (rrr); i ++ )
#define mef(x) memset (x, -1, sizeof (x))
#define mel(x) memset (x, 0, sizeof (x))
#define NIL -1
#define gdboff fclose(stdin), fclose(stdout)
#define gdb freopen("In.in","r",stdin), freopen("Out.out","w",stdout)
#define N 50 + 5
#define M 200000 + 5
using namespace std;
inline int read ()
{
int x = 0;
int f = 1;
char c = getchar ();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar ();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar ();
return x * f;
}
inline void write (int x)
{
if (x < 0)
putchar ('-'), x = -x;
if (x > 9)
write (x / 10);
putchar (x % 10 | 48);
return ;
}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const int A_LEN = 1e6 + 10;
const int MOD = 1e9 + 7;
int n, c;
int w[N], f[N][N][3], p[N];
signed main ()
{
n = read ();
c = read ();
for (int i = 1; i <= n; i ++ )
{
p[i] = read ();
w[i] = read ();
}
for (int i = 1; i <= n; i ++ )
{
for (int k = 0; k <= 2; k ++ )
{
f[i][i][k] = INF; // 初始化
}
}
f[c][c][0] = f[c][c][1] = 0; // 老头所在的位置
for (int s = 1; s <= n - 1; s ++ )
{
for (int i = 1; i + s <= n; i ++ )
{
int j = i + s;
int lt = p[j] - p[i]; // 区间位置长度
ll wt = 0;
for (int wi = 1; wi <= n; wi ++ )
{
if (wi >= i && wi <= j)
continue;
wt += w[wi];
} // 计算除区间内的功率
f[i][j][1] = min (f[i + 1][j][0] + (wt + w[i]) * lt, f[i + 1][j][1] + (wt + w[i]) * (p[i + 1] - p[i]));
f[i][j][0] = min (f[i][j - 1][0] + (wt + w[j]) * (p[j] - p[j - 1]), f[i][j - 1][1] + (wt + w[j]) * lt);
}
}
cout << min (f[1][n][1], f[1][n][0]) << endl;
return 0;
}
//g++ t.cpp -o t -std=c++11 -g
//gdb t