硬币问题:

Coins

1:原始的多重背包 tle

#include<bits/stdc++.h>
using namespace std;
int dp[105][100005];
int n;
int w[105],c[105];
int main(){
    int m;
    while(cin>>n>>m,n||m) {
        ::memset(dp,0,sizeof dp);
        for (int i = 1; i <= n; ++i) {
            cin >> c[i];
        }
        for (int i = 1; i <= n; ++i) {
            cin >> w[i];
            dp[i][w[i]] = 1;
        }
        for (int i = 2; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                for (int k = 0; k <= c[i] && k * w[i] <= j; ++k) {
                    if (dp[i - 1][j] == 1)
                        dp[i][j + k * w[i]] = 1;
                }
            }
        }
        int cnt = 0;
        for (int i = 1; i <= m; ++i) {
            if (dp[n][i] == 1)
                cnt++;
        }
        cout << cnt<<endl;
    }
}

2://///二进制优化,时间复杂度nlog1000*m,会超时,

#include<iostream>
#include<algorithm>
using namespace std;
#include<vector>
int n,m;
int w[105];
int f[100005];
int v[105];
int main(){
    while(cin>>n>>m&&n&&m){
        for (int i = 0; i <=m ; ++i) {
            f[i]=0;
        }
        vector< int >a;
        for (int i = 1; i <=n ; ++i) {
            cin>>w[i];
        }
        for (int i = 1; i <=n ; ++i) {
            cin>>v[i];
        }
        f[0]=1;
        a.push_back(0);
        for(int i=1;i<=n;i++){
            int k=1;
            while(k<=v[i]){
                a.push_back(k*w[i]);
                v[i]-=k;
                k*=2;

            }
            if(v[i]>0){
                a.push_back(v[i]*w[i]);
            }
        }
        f[0]=1;
        for (int i = 1; i <a.size() ; ++i) {
            for (int j = m; j >=a[i] ; --j) {
                if(f[j-a[i]]==1){
                    f[j]=1;
                }
            }
        }
        int cnt=0;
        for (int i = 1; i <=m ; ++i) {
            if(f[i])cnt++;
        }
        cout<<cnt<<endl;

    }
}

3.正解,时间复杂度是n*m,硬币问题,

  • 1.若是j在本i层之前已经被凑出来了,则吧f[j]等于c[i]的数量
  • 2.若是j小于w[i]或者f【j-w[i]】没有被凑出来或者已经消耗完了c[i];则为-1
  • 3.f【j】由w【i】凑出,就等于f【j-w[i]】减1;
    
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int f[100005];
    int n;
    int w[105],c[105];
    int main(){
    int m;
    while(cin>>n>>m,n||m) {
        ::memset(f,-1,sizeof f);
        for (int i = 1; i <= n; ++i) {
            cin >> w[i];
        }
        for (int i = 1; i <= n; ++i) {
            cin >> c[i];
        }
        f[0]=0;
        for (int i = 1; i <=n ; ++i) {
            for (int j = 0; j <=m ; ++j) {
                    if(f[j]>=0)f[j]=c[i];
                    else if(j<w[i]||f[j-w[i]]<=0)f[j]=-1;
                    else f[j]=f[j-w[i]]-1;
            }
        }
        int cnt=0;
        for (int i = 1; i <=m ; ++i) {
            if(f[i]>=0)cnt++;
        }
        cout << cnt<<endl;
    }
    }
posted on 2023-05-04 19:42  IR101  阅读(5)  评论(0编辑  收藏  举报  来源