刷題——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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章