這道題其實和一般的01揹包沒有什麼區別,只是這道題目按照正常的思維去做不行了,因為容量太大,開個10^9的陣列開不了,所以這時候就需要換種思維,這個題剛開始沒理解,後來在網上在題解,發現都說是互換重量和價值,但是一直沒理解什麼意思,後來,仔細想了想那個最最基礎的01揹包是怎麼推出來的才想通了, 也不能說是互換價值和重量,那樣其實並不能加深理解,做完這個題之後,發現又對揹包理解深了一點,寫個部落格,留下紀念
這道題很容易發現其實重量很大,達到10^9,但是價值很小啊,現在就來推一下這個所謂的「互換」是怎麼來的 (其實我覺得還不如從最原始的來,不叫做「互換」好理解點), 最原始的那個式子
dp[i][j]表示當取 i 個, 重量為 j 的時候揹包的最大價值,狀態轉移方程就是 dp[i][j] = max(dp[i - 1][j], dp[i-1][j - weight[i]] + value[i]), 這個式子的意思想必大家都明白吧,前面的那個意思是不取當前這個,後面的這個是取上當前這個物品, 後來再經空間優化之後變成了dp[j] = max(dp[j], dp[j - weight[i]] + value[i]), 仔細觀察會發現二維陣列時,那兩種狀態都是i - 1,所以就可以去掉,但是得注意,迴圈遍歷的時候要逆序,正序的話就成完全揹包了, 忘了說這個dp[j]表示什麼了, dp[j]就是 當取到重量為j 的時候的最大價值。弄明白了這些。這時候就可以來看這個題了, 題目要求和普通的01揹包一樣,求能裝的最大價值,普通方法就是直接找最大價值,現在要換種思維,找最小的重量, 因為同樣價值,重量越小,那麼最後能裝的價值就可能越大,所以這個dp[i][j]就表示 當 取 i 個, 價值為j 的時候的最小重量,狀態轉移方程為 dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - value[i]] + weight[i]), 和那個最初推的一樣,不再羅嗦,空間優化之後狀態轉移方程為dp[j] = min(dp[j], dp[j - value[i]] + weight[i]), 同樣的意思,dp[j]表示 價值為j 的時候的最小重量,到最後只要從最大價值往下遍歷這個dp陣列,只要找到dp[j] <= 揹包重量的時候就直接輸出 j , 這時候j就是最大的。
**如下:
1 #include 2 #include 3 #include4#define min(a,b) a5
6const
int n = 10003;7
intdp[n];
8int weight[102];9
int value[102
];10
intmain()
1122 memset(dp, 0x3f, sizeof(dp));//
初始化陣列要為無窮大,因為是要找最小值,所以預設無窮大
23 dp[0] = 0;24
for (int i = 0; i < n; i++)
2530
for (int i = sum; i >=0; i--)
31if (dp[i] <=w)
3236}37
return0;
38 }
NYOJ 860 又見01揹包
很經典的一道揹包題目,一般情況,我們都是把揹包的容量作為陣列的變數,但是這一道題,揹包容量資料量太大了。10 9 把容量和價值進行互換 include iostream include stdio.h include string include cstring include cmath incl...
nyoj860又見01揹包
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有n個重量和價值分別為wi 和 vi 的 物品,從這些物品中選擇總重量不超過 w 的物品,求所有挑選方案中物品價值總和的最大值。1 n 100 1 wi 10 7 1 vi 100 1 w 10 9 輸入多組測試資料。每組測試資...
nyoj860 又見01揹包
題源 nyoj860 時間限制 1000 ms 記憶體限制 65535kb 難度 3 描述 有n個重量和價值分 別為wi 和 vi 的 物品,從這些物品中選擇總重量不超過 w 的物品,求所有挑選方案中物品價值總和的最大值。1 n 100 1 wi 10 7 1 vi 100 1 w 10 9 輸入多...