题目如下:
输入样例1:
4 100
20
90
60
60
输出样例1:
110
样例1解释
购买前两本书 (20+90) 即可包邮且花费最小。
输入样例2:
3 30
15
40
30
输出样例2:
30
样例2解释
仅购买第三本书恰好可以满足包邮条件。
输入样例3:
2 90
50
50
输出样例3:
100
样例3解释
必须全部购买才能包邮。
题解 or 思路:
看题意 + 数据量 显然是一道金典的 动态规划问题
状态定义:
d
p
[
x
]
dp[x]
dp[x]
如果
d
p
[
x
]
=
1
dp[x] = 1
dp[x]=1 代表我们可以凑出来
x
x
x
如果
d
p
[
x
]
=
0
dp[x] = 0
dp[x]=0 代表我们不能凑出来
x
x
x
转移方程
d p [ j ] ∣ = d p [ j − a [ i ] ] dp[j]\ |= dp[j - a[i]] dp[j] ∣=dp[j−a[i]]
查找答案时,就从 x x x 到 s u m sum sum 查询是否可以构造出来就行,第一个可以构造出来的就是最优答案!
AC 代码如下:
#define buff \
ios::sync_with_stdio(false); \
cin.tie(0);
const int N = 300009;
int n, x, a[35], dp[N];
void solve()
{
cin >> n >> x;
int sum = 0;
for (int i = 1; i <= n; i++)
cin >> a[i], sum += a[i];
dp[0] = 1;
for (int i = 1; i <= n; i++)
for (int j = sum; j >= a[i]; j--)
dp[j] |= dp[j - a[i]];
for (int i = x; i <= sum; i++)
{
if (dp[i])
{
cout << i << '\n';
return;
}
}
}
int main()
{
buff;
solve();
}