暴力解法:枚举每本书选或不选,一共2^n种状态,取其中满足要求的最小值即可
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 35;
int w[N];
int n, x;
int main()
{
scanf("%d%d", &n, &x);
for (int i = 0; i < n; ++ i) scanf("%d", &w[i]);
int res = 1e8;
for (int i = 0; i < (1 << n); ++ i)
{
int sum = 0;
for (int j = 0; j < n; ++ j)
if (i >> j & 1)
sum += w[j];
if (sum >= x) res = min(res, sum);
}
printf("%d\n", res);
return 0;
}
也可以用递归进行暴力枚举
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 35;
int w[N];
int n, x;
int res = 1e8;
void dfs(int u, int sum)
{
if (u == n)
{
if (sum >= x) res = min(res, sum);
return ;
}
dfs(u + 1, sum);
dfs(u + 1, sum + w[u]);
}
int main()
{
scanf("%d%d", &n, &x);
for (int i = 0; i < n; ++ i) scanf("%d", &w[i]);
dfs(0, 0);
printf("%d\n", res);
return 0;
}
不过暴力枚举只能过70%的数据,剩下的就TLE了
==========================分割线==============================
正解:本题可利用01背包模型,转化为选择若干本书,使得总和不超过sum - x的前提下,总和越大越好。
背包容量为sum - x,每个物品的体积为w[i],每个物品的价值为w[i]
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 35, M = 300010;
int w[N], f[M];
int n, x;
int main()
{
scanf("%d%d", &n, &x);
int sum = 0;
for (int i = 0; i < n; ++ i)
{
scanf("%d", &w[i]);
sum += w[i];
}
int m = sum - x;
for (int i = 0; i < n; ++ i)
for (int j = m; j >= w[i]; -- j)
f[j] = max(f[j], f[j - w[i]] + w[i]);
printf("%d\n", sum - f[m]);
return 0;
}