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;
}
posted @ 2020-09-30 15:21  quanjun  阅读(423)  评论(0编辑  收藏  举报