刷题——Coins POJ - 1742

/*
有n种硬币,每个硬币面值为ai,每个硬币有ci种
问用这些硬币支付m元以内的东西,可以支付几种


朴素的方法是:
dp[i][j]表示用前i种硬币能否拼出j
耗时o(nmc) 空间o(nm) 超时,超内存
变化一下:
dp[i][j]表示用前i种硬币拼出j时第i种硬币还剩下多少种
dp[i][j]={
            c[i]:dp[i-1][j]>=0,用i-1种硬币就可以拼出j,第i种硬币无消耗
            -1:j<a[i]||dp[i][j-a[i]]<0,要么第i种硬币面值太大,要么已经在更小的支付中被消耗
            dp[i][j-a[i]]-1,其它情况
}
耗时o(nm) 空间o(nm) 超内存
最后优化:
dp[j]={
        c[i]:dp[j]>=0,......
        -1:j<a[i]||[j-a[i]]<0,......
        dp[j-a[i]]-1,......
}
耗时o(nm) 空间o(m) 通过
Time 2016ms Memory 568kB
*/
#include <stdio.h>
#include <string.h>
int a[105],c[105];
int dp[100005];
int main(){
    int n,m;
    while(scanf("%d %d",&n,&m)&&(n||m)){
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%d",&c[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<=m;j++){
                if(dp[j]>=0){
                    dp[j]=c[i];
                }
                else if(j<a[i]||dp[j-a[i]]<=0){
                    dp[j]=-1;
                }
                else{
                    dp[j]=dp[j-a[i]]-1;
                }
            }
        }
        int num=0;
        for(int i=1;i<=m;i++){
            if(dp[i]>=0)num++;
        }
        printf("%d\n",num);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章