CF598E Chocolate Bar 题解 动态规划

题目链接:https://codeforces.com/problemset/problem/598/E

题目大意:
给一个 (n imes m) 的巧克力块切除总共 (k) 小块(不需要全都切出来,只需要切出来的一些块的总数是 (k) 即可),切的代价为切得那条边小块个数的平方,求最小代价和。

解题思路:

状态:(dp_{i,j,k}) 表示将 (i imes 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
", dfs(n, m, k));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/quanjun/p/13754717.html