传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1575
【题解】
动态规划,令f[i,j]表示前i个选了j个,且第i个必选的最小值。
转移就枚举上一个,再暴力算贡献即可。
复杂度O(n^4)
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 100 + 10; const int mod = 1e9+7, inf = 1e9; # define RG register # define ST static # define ABS(x) ((x) >= 0 ? (x) : -(x)) int n, E, s[M], f[M][M]; int main() { cin >> n >> E; for (int i=1; i<=n; ++i) scanf("%d", s+i); // sort(s+1, s+n+1); for (int i=1; i<=n; ++i) for (int j=1; j<=n; ++j) f[i][j] = inf; for (int i=1; i<=n; ++i) { // f[i,1] f[i][1] = 0; for (int j=1; j<=i-1; ++j) f[i][1] = f[i][1] + 2 * ABS(s[i]-s[j]); for (int j=i+1; j<=n; ++j) f[i][1] = f[i][1] + 2 * ABS(s[i]-s[j]); } for (int i=1; i<=n; ++i) for (int j=2; j<=i; ++j) { f[i][j] = inf; for (int k=j-1; k<i; ++k) { int cur = f[k][j-1]; if(cur == inf) continue; for (int l=k+1; l<=n; ++l) cur = cur - 2 * ABS(s[l] - s[k]); for (int l=k+1; l<=i-1; ++l) cur = cur + ABS(2*s[l] - s[i] - s[k]); for (int l=i+1; l<=n; ++l) cur = cur + 2 * ABS(s[l] - s[i]); f[i][j] = min(f[i][j], cur); } } for (int j=1; j<=n; ++j) { int ans = inf; for (int i=j; i<=n; ++i) ans = min(ans, f[i][j]); // cout << j << ' ' << ans << endl; if(ans <= E) { printf("%d %d ", j, ans); return 0; } } return 0; }