区间DP预处理。
dp[i][j][k]表示大小为i*j的巧克力块,切出k块的最小代价。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const long long INF=9999999999999999; const int maxn=60; long long dp[maxn][maxn][maxn]; int n,m,k; void f() { for(int i=1;i<=30;i++) { for(int j=1;j<=30;j++) { for(int k=1;k<=50;k++) { dp[i][j][k]=INF; if(k>i*j) continue; if(k==0) { dp[i][j][k]=0; continue; } if(k==i*j) { dp[i][j][k]=0; continue; } //行割 for(int s=1;s<=i-1;s++) { for(int h=0;h<=k;h++) { if(dp[s][j][h]==INF) continue; if(dp[i-s][j][k-h]==INF) continue; dp[i][j][k]=min( dp[i][j][k], dp[s][j][h]+dp[i-s][j][k-h]+j*j ); } } //列割 for(int s=1;s<=j-1;s++) { for(int h=0;h<=k;h++) { if(dp[i][s][h]==INF) continue; if(dp[i][j-s][k-h]==INF) continue; dp[i][j][k]=min( dp[i][j][k], dp[i][s][h]+dp[i][j-s][k-h]+i*i ); } } } } } } int main() { f(); int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); printf("%lld ",dp[n][m][k]); } return 0; }