Educational Codeforces Round 1 E.Chocolate Bar(DP)

Educational Codeforces Round 1E:http://codeforces.com/contest/598/problem/E

E. Chocolate Bar
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You have a rectangular chocolate bar consisting of n × m single squares. You want to eat exactly k squares, so you may need to break the chocolate bar.

In one move you can break any single rectangular piece of chocolate in two rectangular pieces. You can break only by lines between squares: horizontally or vertically. The cost of breaking is equal to square of the break length.

For example, if you have a chocolate bar consisting of 2 × 3 unit squares then you can break it horizontally and get two 1 × 3 pieces (the cost of such breaking is 32 = 9), or you can break it vertically in two ways and get two pieces: 2 × 1 and 2 × 2 (the cost of such breaking is 22 = 4).

For several given values nm and k find the minimum total cost of breaking. You can eat exactly k squares of chocolate if after all operations of breaking there is a set of rectangular pieces of chocolate with the total size equal to k squares. The remaining n·m - ksquares are not necessarily form a single rectangular piece.

Input

The first line of the input contains a single integer t (1 ≤ t ≤ 40910) — the number of values nm and k to process.

Each of the next t lines contains three integers nm and k (1 ≤ n, m ≤ 30, 1 ≤ k ≤ min(n·m, 50)) — the dimensions of the chocolate bar and the number of squares you want to eat respectively.

Output

For each nm and k print the minimum total cost needed to break the chocolate bar, in order to make it possible to eat exactly ksquares.

Sample test(s)
input
4
2 2 1
2 2 3
2 2 2
2 2 4
output
5
5
4
0
Note

In the first query of the sample one needs to perform two breaks:

  • to split 2 × 2 bar into two pieces of 2 × 1 (cost is 22 = 4),
  • to split the resulting 2 × 1 into two 1 × 1 pieces (cost is 12 = 1).

In the second query of the sample one wants to eat 3 unit squares. One can use exactly the same strategy as in the first query of the sample.


题目大意:初始有一块n*m的巧克力,每次只能沿一条直线切成两块矩形的巧克力,花费为所切边长的平方。问:最终得到面积和为k的巧克力的最小花费为多少?


做完3到水题,然后就没有然后了(虽然昨晚提前断电断网,但根本原因还是想不到)

感觉自己的想法根本靠不上DP,最终结果是面积的集合,想不出如何表示状态

看了别人的代码才知道:将其在状态转移时分成是否丢弃切下的矩形,即可达到是否属于一个集合的目的


dp[n][m][k]表示用n*m的矩形得到面积和为k的矩形集合的最小花费


①dp[n][m][k]可由dp[n-t][m][k](丢弃t*m的矩形)和dp[n-t][m][k-t*m](不丢弃t*m的矩形)  [1<=t<n]  转移而来,都需要加上m*m的花费

②dp[n][m][k]可由dp[n][m-t][k](丢弃n*t的矩形和dp[n][m-t][k-n*t(不丢弃n*t的矩形)  [1<=t<m]  转移而来,都需要加上n*n的花费


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int n,m,k,t;
int dp[35][35][55];//dp[n][m][k]表示用n*m的矩形得到面积和为k的矩形集合的最小花费

int main() {
    memset(dp,0x3f,sizeof(dp));
    for(n=1;n<=30;++n)
        for(m=1;m<=30;++m)
            if(m*n<=50)//n*m的矩形得到面积为m*n的矩形花费为0
                dp[n][m][m*n]=0;
    for(n=1;n<=30;++n)
        for(m=1;m<=30;++m)
            for(k=1;k<=50;++k) {
                for(t=1;t<n;++t) {
                    dp[n][m][k]=min(dp[n][m][k],dp[n-t][m][k]+m*m);//不丢弃t*m的矩形
                    if(k>t*m)//如果要组成的面积大于t*m的矩形,丢弃它
                        dp[n][m][k]=min(dp[n][m][k],dp[n-t][m][k-t*m]+m*m);
                }
                for(t=1;t<m;++t) {
                    dp[n][m][k]=min(dp[n][m][k],dp[n][m-t][k]+n*n);//不丢弃n*t的矩形
                    if(k>n*t)//如果要组成的面积大于n*t的矩形,丢弃它
                        dp[n][m][k]=min(dp[n][m][k],dp[n][m-t][k-n*t]+n*n);
                }
            }
    scanf("%d",&t);
	while(t--) {
        scanf("%d%d%d",&n,&m,&k);
        printf("%d\n",dp[n][m][k]);
	}
	return 0;
}


你可能感兴趣的:(dp,codeforces)