zoukankan      html  css  js  c++  java
  • POJ 1742 Coins(多重背包?)

    题解

    一个自然的思路是对于每一个物品做一次01背包

    然后T飞了。

    试着用二进制拆分,还是T了。

    单调队列,对不起,懒,不想写。

    我们这样想。设dp[i]代表i这个面值前几种硬币是否能凑到

    然后对于每一个i,我们用used[i]代表要凑到i这个值至少要多少个当前这种硬币

    然后used可以o(m)得到(当dp[i]=1时,used[i]=0,否则dp[i]=used[dp[i-a]]+1),对于一个used[i]<=c我们把dp[i]变为1.

    完成了转移这样复杂度为O(n*m)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=110;
     8 const int M=100100;
     9 int n,m,dp[M],a[N],c[N],ans,used[M];;
    10 int main(){
    11     while(scanf("%d%d",&n,&m)!=EOF){
    12         if(n==0&&m==0)break;
    13         memset(dp,0,sizeof(dp));
    14         dp[0]=1;
    15         for(int i=1;i<=n;i++){scanf("%d",&a[i]);}
    16         for(int i=1;i<=n;i++){scanf("%d",&c[i]);}
    17         for(int i=1;i<=n;i++){
    18             for(int j=0;j<=m;j++)used[j]=0;
    19             for(int j=a[i];j<=m;j++){
    20                 if(!dp[j]&&dp[j-a[i]]&&used[j-a[i]]<c[i]){
    21                     dp[j]=1;used[j]=used[j-a[i]]+1;
    22                 }
    23             }
    24         }
    25         ans=0;
    26         for(int i=1;i<=m;i++)ans+=dp[i];
    27         printf("%d
    ",ans);
    28     }
    29     return 0;
    30 }
  • 相关阅读:
    Java Arrays 的基础知识
    Java 基础知识
    C
    165. 小猫爬山 (dfs)
    164. 可达性统计
    数码 美团资格赛(整数分块)
    1079 中国剩余定理(模板)
    5814: 余数之和(整数分块)
    Greedy Sequence(主席树-区间小于每个数的最大值)
    XKC's basketball team(单调栈+二分)
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9745866.html
Copyright © 2011-2022 走看看