Codeforces Round #787 (Div. 3)-G
题目
解题思路
这道题首先需要明白一个trick:
需要用前缀和来判断操作次数。
如果进行操作1,那么prefix(i-1)++
如果进行操作2,那么prefix(i)–
也就是说可以通过对位的这个前缀和的差的绝对值的和来判断出进行的操作的次数
然后就可以使用DP来求解最少的次数
那么这里为了保证是非上升的序列,所以最后一位K是倒序
然后每次可以取j=k,m 来更新
因为K是倒序的,后面的值刷新是比前面慢的,所以就保证了后边的值是小于等于前面的
如果要求非下降序列,那么K正序即可
#include <bits/stdc++.h>
using namespace std;
const int N = 255;
typedef long long LL;
int a[N], f[N][N];
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) cin >> a[i], a[i] += a[i - 1];
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for(int k = 0; k <= m; k ++ ) {
for(int i = 1; i <= n ; i ++ )
for(int j = k; j <= m; j ++ )
f[i][j] = min(f[i][j], f[i - 1][j - k] + abs(j - a[i]));
}
cout << f[n][m];
return 0;
}