CF598E Chocolate Bar 题解 动态规划
题目链接:https://codeforces.com/problemset/problem/598/E
题目大意:
给一个 \(n \times m\) 的巧克力块切除总共 \(k\) 小块(不需要全都切出来,只需要切出来的一些块的总数是 \(k\) 即可),切的代价为切得那条边小块个数的平方,求最小代价和。
解题思路:
状态:\(dp_{i,j,k}\) 表示将 \(i \times j\) 的巧克力切除 \(k\) 块的最小代价和。
状态转移方程:略。
示例代码:
#include <bits/stdc++.h>
using namespace std;
int f[31][31][51];
bool vis[31][31][51];
int T, n, m, k;
int dfs(int n, int m, int k) {
if (n > m) return dfs(m, n, k);
if (vis[n][m][k]) return f[n][m][k];
vis[n][m][k] = true;
if (k == 0 || n * m == k) return f[n][m][k] = 0;
for (int i = 1; i <= n/2; i ++) {
for (int j = 0; j <= min(i*m, k); j ++) {
f[n][m][k] = min(f[n][m][k], dfs(i, m, j) + dfs(n-i, m, k-j) + m * m);
}
}
for (int i = 1; i <= m/2; i ++) {
for (int j = 0; j <= min(i*n, k); j ++) {
f[n][m][k] = min(f[n][m][k], dfs(n, i, j) + dfs(n, m-i, k-j) + n * n);
}
}
return f[n][m][k];
}
int main() {
memset(f, 0x3f, sizeof(f));
scanf("%d", &T);
while (T --) {
scanf("%d%d%d", &n, &m, &k);
printf("%d\n", dfs(n, m, k));
}
return 0;
}