1. 程式人生 > >分蛋糕

分蛋糕

時間 思想 min 最小 cstring cor ostream mes con

總時間限制:
1000ms
內存限制:
65536kB
描述

有一塊矩形大蛋糕,長和寬分別是整數wh。現要將其切成m塊小蛋糕,每個小蛋糕都必須是矩形、且長和寬均為整數。切蛋糕時,每次切一塊蛋糕,將其分成兩個矩形蛋糕。請計算:最後得到的m塊小蛋糕中,最大的那塊蛋糕的面積下限。

假設w= 4, h= 4, m= 4,則下面的切法可使得其中最大蛋糕塊的面積最小。

技術分享

假設w= 4, h= 4, m= 3,則下面的切法會使得其中最大蛋糕塊的面積最小:

技術分享

輸入
共有多行,每行表示一個測試案例。每行是三個用空格分開的整數w, h, m ,其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 當 w = h = m = 0 時不需要處理,表示輸入結束。
輸出
每個測試案例的結果占一行,輸出一個整數,表示最大蛋糕塊的面積下限。
樣例輸入
4 4 4
4 4 3
0 0 0
樣例輸出
4
6
來源:openjudge
參考代碼
/**
一看就是按遞歸的思想轉換成動規

dp[w][h][m],w:長h:寬m:塊數
表示長w寬h的蛋糕切m刀所能得到最大塊蛋糕面積的最小值

邊界條件:
①w*h<m,dp[w][h][m]=INF(最多w*h塊,每塊都分成1的大小,所以不會超過m塊)
②m=1,dp[w][h][1]=w*h

每一刀,看是橫切,還是豎切
取切後的最大塊中最小的
假設初始蛋糕左右是長上下是寬

得到的小塊蛋糕繼續切,直到切完m-1刀
*/
///代碼摘自:
http://www.cnblogs.com/candy99/p/5792478.html #include <iostream> #include <cstring> using namespace std; const int N=22,INF=1e9; int f[N][N][N],w,h,m; void solve(){ memset(f,0,sizeof(f)); //邊界條件 for(int i=1;i<=w;i++) for(int j=1;j<=h;j++) f[i][j][1]=i*j; for(int
i=1;i<=w;i++) for(int j=1;j<=h;j++) for(int k=2;k<=min(i*j,m);k++){ f[i][j][k]=INF; //橫切 for(int t=1;t<i;t++){ for(int p=1;p<k;p++) f[i][j][k]=min(f[i][j][k],max(f[t][j][p],f[i-t][j][k-p])); } //豎切 for(int t=1;t<j;t++){ for(int p=1;p<k;p++) f[i][j][k]=min(f[i][j][k],max(f[i][t][p],f[i][j-t][k-p])); } } } int main(int argc, const char * argv[]) { while(cin>>w>>h>>m){ if(w==0&&h==0&&m==0) break; solve(); cout<<f[w][h][m]<<"\n"; } return 0; }

該題一看就能知道用DP,可是實現起來有點復雜,我也沒有徹底搞明白,歡迎推薦更詳細,更易懂的題解,感激不盡!

分蛋糕