POJ1742 Coin 背包 男人8题系列

传送门

题意:给你N种硬币,以及每个硬币的个数,问能组成多少种不同的价值。
题解:介于多重背包和完全背包之间?我是这么理解的。
具体解释见代码
AC-CODE

//#include 
#include
#include
#include
#include 
using namespace std;
typedef long long ll;
typedef unsigned  long long ull;
const int mx = 2e5 + 7;
const ll inf = 9e12 + 7;
int n,m;
int ha[mx],g[mx],a[mx],c[mx];
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while(cin >> n >> m) {
        if (n == 0 && m == 0)
            break;
        memset(ha, 0, sizeof(ha));
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>c[i];
        ha[0]=1;
        for(int i=1;i<=n;i++) {
            for(int j=0;j<=m;j++){ //本来是滚动数组g[i][j]表示第i种硬币到j价值的最小花费个数,因为每次都是在讨论第I个了,所以没有必要开两维,所以我滚了一个维度。时间换空间。
                g[j] = 0;
            }
            for (int j = 0; j <= m; j++) {
                if (ha[j] && ha[a[i] + j] == 0 && (a[i] + j) <= m && g[j] < c[i]) {//就是ha[j]前一个有了,且a[i]+j也能
                //同时a[i]+j要小于M,题目要求
                    ha[a[i] + j] = 1;
                    g[a[i] + j] = g[j] + 1;//,最后g[j]花费的个数不能超过每种硬币的个数c[i]-1。然后是一个完全背包
                }
            }
        }
        int ans = 0;
        for(int i=1;i<=m;i++){
            if (ha[i])
                ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(背包)