hdu 2546 详解用0-1背包思想解决问题

来源:互联网 发布:js回调函数有什么用 编辑:程序博客网 时间:2024/06/02 03:37

这道题,我一共WA了5次。

基本上,每一次我都发现了自己思维上的问题。

想花一点时间认真的来解释一下我的解法。


首先附AC代码:

#include<iostream>#include<algorithm>using namespace std;#define N 1005int n;int v[N];int val;int re[N][N];void zeroOneBack(){int i = n - 1,j,k,temp1,temp2;for (j = 0; j < 5; j++){re[i][j] = j;}for (; j <= val; j++){re[i][j] = j - v[i];}for (k = i - 1; k >= 0; k--){for (j = 0; j < 5 ; j++){re[k][j] = re[k + 1][j];}for (; j <= val; j++){temp1 = re[k + 1][j];if (j - v[k] >= 0){temp2 = re[k + 1][j - v[k]];}else{temp2 = j - v[k];}re[k][j] = temp1 < temp2 ? temp1 : temp2;}}}int main(){int i;while (cin >> n&&n != 0){for (i = 0; i < n; i++){cin >> v[i]; }sort(v, v + n);cin >> val;zeroOneBack();cout <<re[0][val]<< endl;}return 0;}


我看了网上的解法,大部分人都先对价值最高的先进行处理,然后再进行0-1背包。

我一开始不理解这种做法,其实这种做法是有它的必要性的。一会详细的解释。


数组 re[i][j] 代表 i物品在饭卡中还剩下j元时,有可能使得饭卡能达到的最低金额。

比如re[3][6] = -2 表示如果我要选择买不买3号时,当我饭卡内还剩下6元时,可能能达到的最低金额是-2元。


0-1背包问题自底向上,所以从最后一个物品开始,

首先进行初始化,

如果饭卡内的金额小于5,则不管够不够,都不能买(要特别注意这个初始化)

所以

for (j = 0; j < 5; j++){re[i][j] =<span style="color:#ff0000;"> j</span>;}


对于最后一个物品而言,如果饭卡内的金额大于5元,则都可以买

for (; j <= val; j++){re[i][j] = j - v[i];}
这里就要特别提出在进入0-1背包之前,我先进行了排序:

sort(v, v + n);
因为,直接0-1背包,价格大的物品再前,而价格小的物品在后,价格大的物品就会把价格小的物品被选择的机会给剥夺,

这里我给出一组测试用例,大家比较一下就知道了。

如果不排序,

10
3 10 10 10 11 1 3 4 5 6
7
这组用例的结果会是 -4

10
3 10 10 10 1 11 3 4 5 6
7

这组用例的结果会是 -5


然后进行0-1背包的选择,这个就没什么好说的啦。


另外提供几组测试用例:

2

1 1

5

4

1

10

3

3


能够通过这些的话

我相信你应该能够AC啦!


继续加油刷DP

1 0
原创粉丝点击