Nine Packsa (01背包)

Nine Packs
“It’s like how hot dogs come in packs of ten, and buns come in packs of eight or twelve — you have to buy nine packs to make it come out even.”
This is a quote from the 1986 movie, “True Stories”, and it’s true; well, almost true. You could buy four packs of 10 hotdogs and five packs of 8 buns. That would give you exactly 40 of each. However, you can make things even with fewer packs if you buy two packs of 10 hotdogs, along with a pack of 8 buns and another pack of 12 buns. That would give you 20 of each, using only 4 total packs.

For this problem, you’ll determine the fewest packs you need to buy to make hotdogs and buns come out even, given a selection of different bun and hotdog packs available for purchase.

Input
The first input line starts with an integer, H, the number of hotdog packs available. This is followed by H integers, h1…hH, the number of hotdogs in each pack. The second input line starts with an integer, B, giving the number of bun packs available. This is followed by B integers, b1…bB, indicating the number of buns in each pack. The values H and B are between 0 and 100, inclusive, and the sizes of the packs are between 1 and 1000, inclusive. Every available pack is listed individually. For example, if there were five eight-bun packs available for purchase, the list of bun packs would contain five copies of the number eight.

Output
If it’s not possible to purchase an equal number of one or more hotdogs and buns, just output “impossible”. Otherwise, output the smallest number of total packs you can buy (counting both hotdog and bun packs) to get exactly the same number of hotdogs and buns.

Sample Input 1
4 10 10 10 10
10 8 8 8 12 12 12 8 8 12 12
Sample Output 1
4
Sample Input 2
4 7 7 14 7
3 11 22 11
Sample Output 2
impossible

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int dp1[N], s1[N], dp2[N], s2[N];
int a[N], b[N];
void solve(int dp[], int a[], int s[], int sum, int n) {
    dp[0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = sum; j >= a[i]; j--) {
            if (dp[j - a[i]] && dp[j] == 0) {
                dp[j] = 1;
                s[j] = s[j - a[i]] + 1;
            } else if (dp[j - a[i]] && dp[j]) {
                s[j] = min(s[j], s[j - a[i]] + 1);
            }
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    int n, m, sum1 = 0, sum2 = 0;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        sum1 += a[i];
    }
    solve(dp1, a, s1, sum1, n);
    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> b[i];
        sum2 += b[i];
    }
    solve(dp2, b, s2, sum2, m);
    sum1 = min(sum1, sum2);
    int ans = 1e5;
    for (int i = 1; i <= sum1; i++) {
        if (s1[i] && s2[i]) ans = min(ans, s1[i] + s2[i]);
    }
    if (ans != 1e5)
        cout << ans << '\n';
    else
        puts("impossible");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值