Codeforces Round #787 (Div. 3) Sorting Pancakes(dp)
链接
题意:给出一个长度为
n
n
n的数组,给出总和
m
m
m,输入每一个位置的
a
[
i
]
a[i]
a[i],每次操作可以让
(
a
[
i
]
+
1
&
&
a
[
i
+
1
]
−
1
)
∣
∣
(
a
[
i
]
−
1
&
&
a
[
i
+
1
]
+
1
)
(a[i]+1\&\&a[i+1]-1)||(a[i]-1\&\&a[i+1]+1)
(a[i]+1&&a[i+1]−1)∣∣(a[i]−1&&a[i+1]+1),为最少操作多少次可以让这个数组变成不递减
思路:还不会
n
3
n^3
n3,首先假设数组a变成了b,那么他的花费一定是
a
b
s
(
s
a
−
s
b
)
abs(s_{a}-s_b)
abs(sa−sb),其中
s
s
s是前缀和,不为什么,然后定义
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]为前i个数字,前缀和为j,最后一个数字为k。枚举上一个的前缀和和k,转移:
d
p
[
i
]
[
j
]
[
k
]
=
m
i
n
(
d
p
[
i
]
[
j
]
[
k
]
,
d
p
[
i
−
1
]
[
j
−
k
]
[
t
]
+
a
b
s
(
s
i
−
j
)
)
dp[i][j][k]=min(dp[i][j][k],dp[i-1][j-k][t]+abs(s_i-j))
dp[i][j][k]=min(dp[i][j][k],dp[i−1][j−k][t]+abs(si−j))
#include<bits/stdc++.h>
using namespace std;
int dp[255][255][255], a[255];
int main()
{
int n, m;
cin >> n >> m;
memset(dp, 0x3f, sizeof (dp));
dp[0][0][m] = 0;
for (int i = 1; i <= n; i++) {cin >> a[i]; a[i] += a[i - 1];}
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= j; k++) {
for (int t = k; t <= m; t++) {
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - k][t] + abs(a[i] - j));
}
}
}
}
int ans = 0x3f3f3f3f;
for (int j = 0; j <= m; j++) {
ans = min(ans, dp[n][m][j]);
}
cout << ans ;
return 0;
}