zoukankan      html  css  js  c++  java
  • POJ1742--Coins(动态规划)

    People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
    You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

    Input

    The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

    Output

    For each test case output the answer on a single line.

    Sample Input

    3 10
    1 2 4 2 1 1
    2 5
    1 4 2 1
    0 0
    

    Sample Output

    8
    4



    #include<iostream>
    #include<algorithm>
    #include<string.h>
    int dp[103][100003];
    int val[103],num[103];
    using namespace std;
    int main(){
        int n,m;
        while(cin>>n>>m&&!(n==0&&m==0)){
            memset(dp,0,sizeof(dp));
            for(int i=0;i<n;i++){
                cin>>val[i];
            }
            for(int i=0;i<n;i++){
                cin>>num[i];
            }
            dp[0][0]=1;
            for(int i=0;i<n;i++){
                for(int j=0;j<=m;j++){
                    for(int w=0;w<=num[i]&&w*val[i]<=j;w++){
                        dp[i+1][j]|=dp[i][j-w*val[i]];
                    }
                }
            }
            int ans=count(dp[n]+1,dp[n]+1+m,1);
            cout<<ans<<endl;    
        }
        return 0;
    } 
    dp[i+1][j]表示前i种数字能否拼成j
    一般用DP求取bool结果的话会有不少浪费,同样的复杂度可以获得很多信息

    优化

    dp[i+1][j]:用前i种数加和得到j时第i种数最多能剩几个

    1. dp[i][j] := 用前i种硬币凑成j时第i种硬币最多能剩余多少个(-1表示配不出来)
    2.             如果dp[- 1][j] >= 0(前i-1个数可以凑出j,那么第i个数根本用不着)直接为C[i]
    3. dp[i][j] =  如果< A[i]或者dp[i][- a[i]] <=0 (面额太大或者在配更小的数的时候就用光了)-1
    4.             其他(将第i个数用掉一个) dp[i][j-a[i]] - 1
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    int dp[103][100003];
    int val[103],num[103];
    using namespace std;
    int main(){
        int n,m;
        while(cin>>n>>m&&!(n==0&&m==0)){
            memset(dp,-1,sizeof(dp));
            for(int i=0;i<n;i++){
                cin>>val[i];
            }
            for(int i=0;i<n;i++){
                cin>>num[i];
            }
            dp[0][0]=0;
            for(int i=0;i<n;i++){
                for(int j=0;j<=m;j++){
                    if(dp[i][j]>=0)
                        dp[i+1][j]=num[i];
                    else if(j<val[i]||dp[i+1][j-val[i]]<=0){
                        dp[i+1][j]=-1; 
                    }
                    else{
                        dp[i+1][j]=dp[i+1][j-val[i]]-1;
                    }
                }
            } 
            int ans=0;
            for(int i=1;i<=m;i++){
                if(dp[n][i]!=-1)
                    ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    } 

     数组重复利用

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    int dp[100005];
    int val[103],num[103];
    using namespace std;
    int main(){
        int n,m;
        while(cin>>n>>m&&!(n==0&&m==0)){
            memset(dp,-1,sizeof(dp));
            for(int i=0;i<n;i++){
                cin>>val[i];
            }
            for(int i=0;i<n;i++){
                cin>>num[i];
            }
            dp[0]=0;
            for(int i=0;i<n;i++){
                for(int j=0;j<=m;j++){
                    if(dp[j]>=0)
                        dp[j]=num[i];
                    else if(j<val[i]||dp[j-val[i]]<=0){
                        dp[j]=-1; 
                    }
                    else{
                        dp[j]=dp[j-val[i]]-1;
                    }
                }
            } 
            int ans=0;
            for(int i=1;i<=m;i++){
                if(dp[i]!=-1)
                    ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    } 
  • 相关阅读:
    Chrome 和 FireFox 查看伪类:active,:hover,:focus样式
    为什么需要清除浮动float,及解决办法
    Chrome 控制台使用之配置网速
    Vue 和 浏览器 之Vue项目在浏览器中运行并使用debug
    CSS里不为人知的秘密(02)之常见属性使用
    ImageMagick 简单使用
    php 使用gmail发送邮件之---gmail授权申请开通
    vue复习知识记录【2】 v-if v-show vfor
    vue复习知识记录【1】 绑定字段、绑定事件、使用方法、使用计算
    解决Selenium下使用Firefox的findElement速度非常慢的问题
  • 原文地址:https://www.cnblogs.com/albert67/p/10319553.html
Copyright © 2011-2022 走看看