题目
思路
d p dp dp 状态转移方程:
- d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j − 1 ] , d p [ i ] [ j ] ) ( j > 0 ) dp[i][j] = min(dp[i-1][j-1],dp[i][j]) (j>0) dp[i][j]=min(dp[i−1][j−1],dp[i][j])(j>0)
- d p [ i ] [ j ] = m i n ( d p [ i − 2 ] [ j ] + a [ i ] − a [ i − 1 ] , d p [ i ] [ j ] ) ( i > 1 ) dp[i][j]=min(dp[i-2][j]+a[i]-a[i-1],dp[i][j])(i>1) dp[i][j]=min(dp[i−2][j]+a[i]−a[i−1],dp[i][j])(i>1)
d p [ i ] [ j ] dp[i][j] dp[i][j] 表示从前 i i i 个里选 j j j 个放到盒子里;
AC代码
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <string>
#include <queue>
#define x first
#define y second
using namespace std;
const double eps = 1e-12;
const int N = 300010, P = 13331;
const int mod = 100003;
typedef pair<double, double> PDD;
typedef long long ll;
typedef unsigned long long ull;
const double pi = acos(-1);
int n, k;
ll a[N];
ll dp[N][25];
int main()
{
cin >> n >> k;
for (int i = 1; i <= 2 * n + k; i++) cin >> a[i];
sort(a + 1, a + 2 * n + k + 1);
memset(dp, 0x3f, sizeof dp);
for (int i = 0; i <= k; i++)dp[i][i] = 0;
for (int i = 1; i <= 2 * n + k; i++) {
for (int j = 0; j <= i && j <= k; j++) {
if (j) dp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);
if (i > 1) dp[i][j] = min(dp[i][j], dp[i - 2][j] + a[i] - a[i - 1]);
}
}
cout << dp[2 * n + k][k] << endl;
return 0;
}