原题链接:释放囚犯 - 洛谷
思路:反着考虑其实就是区间dp,类似石子合并问题,不同点是每次合并的时候记得把断点的个数加上而且要减去一个断点(每次合并的时候都是一个断点的两边进行合并)
注意初始化其实就是len为1的时候即f[i][i] = 0(对单独一堆石子的操作代价为0)。
AC代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define PII pair<int,int>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for(int i = n; i >= 1; ++i)
using namespace std;
const double pi = acos(-1.0);
const int N = 1010;
int a[N], s[N], b[N];
int f[N][N];
int n, m;
int main()
{
scanf("%d %d", &n, &m);
rep(i, m) scanf("%d", &a[i]);
m++;
a[m] = n + 1;
rep(i, m) b[i] = a[i] - a[i - 1] - 1;
rep(i, m) s[i] = s[i - 1] + b[i];
for(int len = 2; len <= m; len++)
for(int i = 1; i + len - 1 <= m; i++)
{
int j = i + len - 1;
f[i][j] = INF;
for(int k = i; k < j; k++)
f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + s[j] - s[i - 1] + j - i - 1);
}
printf("%d", f[1][m]);
return 0;
}