CF #EDU R1 E

最二的一次了~我开始以为是带有贪心的DP,谁知道想错了。后来才想明白,暴力二分+记忆化DP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int INF=(1<<29);
int dp[35][35][55];
 
int dfs(int n,int m,int k){
/// if(n>m) swap(n,m);
    if(dp[n][m][k]!=-1){
        return dp[n][m][k];
    }
    if(k>n*m){
        dp[n][m][k]=INF;
        return INF;
    }
    if(k==n*m){
        dp[n][m][k]=0;
        return 0;
    }
     
    dp[n][m][k]=INF;
    for(int i=1;i<=m/2;i++){
        for(int j=0;j<=min(i*n,k);j++){
            dp[n][m][k]=min(dp[n][m][k],dfs(n,i,j)+dfs(n,m-i,k-j)+n*n);
        }
    }
     
    for(int i=1;i<=n/2;i++){
        for(int j=0;j<=min(i*m,k);j++){
            dp[n][m][k]=min(dp[n][m][k],dfs(i,m,j)+dfs(n-i,m,k-j)+m*m);
        }
    }
     
    return dp[n][m][k];
}
 
 
int main(){
    int n,m,k;
    int T;
    scanf("%d",&T);
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<=30;i++)
        for(int j=0;j<=30;j++) dp[i][j][0]=0;
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
   ///     ans=(1LL<<60);
    /// if(n>m) swap(n,m);
        if(dp[n][m][k]==-1)
            dfs(n,m,k);
        cout<<dp[n][m][k]<<endl;
    }
     
    return 0;
}

  

posted @   chenjunjie1994  阅读(165)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示