#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n, B, S = 0;
int h[25];
bool f[20000005];
struct poj3628 {
/*【问题描述】:有n头奶牛,每头奶牛i有身高h[i],有一个高为B的书架,
* 要求选出奶牛的一个子集J,使得sum{h[i]}-B最小且sum{h[i]}-B>=0(i属于J)
*/
/*【解题思路】:考虑令f[n]表示前n头奶牛所能达到的“最有高度”(指超出B且最小的高度和),
* 但是这并不能满足最优子结构,因为原问题的解和子问题的解没有依赖关系。
* 令f[n][H]表示前n头牛中是否存在一个集合使得其高度和为H,
* 则
* [递推关系]:f[n][H]=f[n-1][H] || f[n-1][H-h[n]]
* [边界条件]:f[x][0]=1
* 由于每次决策只跟“上一层”的相关,可以采用一维数组来保存“上一层”的决策
*/
void work() {
while (cin >> n >> B) {
for (int i = 1; i <= n; i++) {
cin >> h[i];
S += h[i];
}
memset(f, 0, sizeof(f));
f[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = S; j >= h[i]; j--) {
f[j] = f[j] || f[j - h[i]];
}
}
int ans = 1 << 30;
for(int i = B; i <= S; i++)
if (f[i]) {
ans = i - B;
break;
}
cout << ans << endl;
}
}
};
int main()
{
poj3628 solution;
solution.work();
return 0;
}
poj3628-Bookshelf2(01背包)
最新推荐文章于 2018-03-03 17:15:08 发布