STDOJ 木木不哭┭┮﹏┭┮(DP)
思路:
赛时看到这个题一点思路都没有,看到题解发现是一道
d
p
dp
dp,呀,
d
p
dp
dp的太妙了,天老爷呦。
k k k的范围不是很大,所以我们对于该题的dp数组可以定义为一个二维数组 d p [ x ] [ k ] dp[x][k] dp[x][k],表示为在前x个玩具中取k个放入箱子的最小难过值。
由于我们的难过值是通过两个相邻的数来计算的所以我们可以推得
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
2
]
[
j
−
1
]
+
a
[
i
]
−
a
[
i
−
1
]
)
dp[i][j]=min(dp[i][j],dp[i-2][j-1]+a[i]-a[i-1])
dp[i][j]=min(dp[i][j],dp[i−2][j−1]+a[i]−a[i−1])
但是我们发现,当
j
j
j为
1
1
1的时候,这个式子并不能表达出对应的情况,那么我们说,当j为1时,就是说对于前
i
i
i个玩具取1个放入箱子的最小难过值,那此时我们只取一个玩具,所以此时的状态方程应为:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
1
]
)
;
dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
dp[i][j]=min(dp[i][j],dp[i−1][j−1]);
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
#define eps 0.00000001
//#define x first
//#define y second
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
int n, k;
ll a[N];
ll dp[N][30];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n * 2 + k; i++)cin >> a[i];
sort(a + 1, a + 1 + 2 * n + k);
for (int i = 0; i <= n * 2 + k; i++)
for (int j = 0; j <= 30; j++)
if (i != j)
dp[i][j] = 0x3f3f3f3f;
else dp[i][j] = 0;
for (int i = 1; i <= 2 * n + k; i++)
{
for (int j = 0; j <= k; j++)
{
if (j) dp[i][j] = min(dp[i - 1][j - 1], dp[i][j]);
if (i >= 2) dp[i][j] = min(dp[i - 2][j] + a[i] - a[i - 1], dp[i][j]);
}
}
cout << dp[2 * n + k][k] << endl;
}
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// Buddha blesses the code with no bugs