Codeforces Problem 598E - Chocolate Bar

Chocolate Bar

题意: 有一个n*m(1<= n,m<=30)的矩形巧克力,每次能横向或者是纵向切,且每次切的花费为所切边长的平方,问你最后得到k个单位巧克力( k <= min(n*m,50) )的最小花费是多少?

思路: 数据规模不大,但是贪心不能得到最优解,很自然想到了dp;里面涉及到行的减少和列的减少,在dp[][]表示中必定要以行数和列数作为dp的含义,但是好像这还不够,如果单单只是一个二维的dp[][]那这个表示的是取了(或者还需)几个单位巧克力呢?
==>三维dp[n][m][k]:当还剩下n行m列还需要取k个单位巧克力时的最小花费;
转移式就是对每个”可切”的行||列遍历,取最小的花费;注意将n,m分开后,还要对之后各自所要得到的巧克力的数量进行划分,即对k进行遍历(从0开始);即dp数组作为记忆,否则直接dfs会TLE.

#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0;i < (n);i++)
#define inf 0x3f3f3f3f
int dp[33][33][55];
int dfs(int n,int m,int k)
{
    if(k <= 0||n * m == k)return 0;
    int &ret = dp[n][m][k];
    if(ret) return ret;
    else ret = inf;
    for(int i = 1;i < n;i++){
        for(int j = 0;j <= k;j++)
        ret = min(ret, dfs(i,m,j) + dfs(n-i,m,k - j) + m*m);
    }
    for(int i = 1;i < m;i++){
        for(int j = 0;j <= k;j++)
            ret = min(ret, dfs(n,i,j) + dfs(n,m-i,k - j) + n*n);
    }
    return ret;
}
int main()
{
    int T,n,m,k;
    cin>>T;
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        printf("%d\n",dfs(n,m,k));
    }
}
View Code

 

 

 

posted @ 2016-01-24 11:54  hxer  阅读(265)  评论(0编辑  收藏  举报