有一塊x*y的布,可以裁剪成n種不同的小碎步布,剪成xi*yi的碎布可以獲得wi元,問將這塊布剪成小碎布最多能獲得多少錢?只能橫著剪或者豎著剪,不能從中間摳出一塊
二維dp,dp[j][k]表示j*k的布剪成小碎布最多能得到多少錢,j*k可以由三個小長方形組成:(這裡有切割方式)
1、xi*yi、 j*(k-xi)、 (j-xi)*yi
2、xi*yi、 xi*(k-yi)、 (j-xi)*k
3、xi*yi、 j*(k-xi)、 (j-yi)*xi
4、xi*yi、 yi*(k-xi)、 (j-yi)*k
所以轉移方程式是:
dp[j][k] = max(dp[j][k], max(dp[j-xi][k]+dp[xi][k-yi], dp[j][k-yi]+dp[j-xi][yi])+wi);
dp[j][k] = max(dp[j][k], max(dp[j-yi][k]+dp[yi][k-xi], dp[j][k-xi]+dp[j-yi][xi])+wi);
重點來了!
網上的絕大多數部落格式直接用以下**得到的dp[x][y]作為最終的值輸出,我覺得這並不是最終的正確答案,下面的**過不了hdu -discuss裡面的乙個資料: 1
4 8 26
1 5 1
3 7 10
3 19 500
5 10 1000
這個答案應該是2521
布剪成小碎布之後還剩下一些沒有價值的布,這有時會造成dp[x][y]偏小(我覺得這也是為什麼三個for位置換了之後,直接輸出dp[x][y]會wa的原因),
需要再加上**中的兩句話
下面這兩個**都是ac的
#include #include #include #include #include using namespace std;
int dp[1010][1010];
int main()
if(j>=yi && k>=xi)}}
} int ans = dp[x][y];//以下兩句是我認為要加上去的
for(int i=0; i<=x; i++) ans = max(ans, dp[i][y]+dp[x-i][y]);
for(int i=0; i<=y; i++) ans = max(ans, dp[x][i]+dp[x][y-i]);
printf("%d\n", ans);
} return 0;
}
#include #include #include #include #include using namespace std;
int dp[1010][1010];
int x[15], y[15], w[15];
int main()
if(j>=y[i] && k>=x[i])}}
} int ans = dp[x][y];
for(int i=0; i<=x; i++) ans = max(ans, dp[i][y]+dp[x-i][y]);
for(int i=0; i<=y; i++) ans = max(ans, dp[x][i]+dp[x][y-i]);
printf("%d\n", ans);
} return 0;
}
HDU 3127 WHUgirls 二維完全揹包
題意 給出乙個長為a,寬為b的布,再給出n個圍巾的規格 長x,寬y,價值c 問怎樣裁剪能夠得到最大的價值。第一次做的時候不會 然後放到今天做 發現還是不會 於是又 看題解了 因為相同規格的圍巾可以重複剪多次,且圍巾的長和寬相當於兩個約束,所以可以轉換為二維費用的完全揹包問題。然後就是圍巾的裁剪 第一...
hdu 3496 二維0 1揹包
很典型的一道二維揹包的題目,在保證時間不超出l的情況下還要保證碟片恰好為m。第一次做二維揹包,錯了n多次,原來才發現陣列中應該為i,不應該為j。include include include include include using namespace std const int inf 1000...
hdu 2159 FATE (二維揹包)
解題報告 二維揹包的問題,如果沒有看過的話,建議去看看揹包9講中的第五個問題。本題中有每殺乙個怪,會獲得一定的經驗,同時減少一定的忍耐度,我用二維陣列dp來存放每次獲得的經驗值,b i 為每次消耗的忍耐 所以可以的到遞推關係式 dp i j max dp i b i j 1 dp i j 資料有點多...