poj 1742 背包

n 个物品  背包体积m

n 个物品的价值  n 个物品的数目   

参考http://www.cnblogs.com/xinsheng/archive/2013/12/04/3458362.html

分3种情况

1 个数只有1个    显然是0 1  n*c

2  价值*数目>m  完全背包    n*c

3  用队列优化   这边好像不是单调队列  

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#include<stack>

using namespace std;

#define ll   __int64
#define MAXN  100010
#define inf  2000000007
#define mod 1000000007
int a[MAXN],c[MAXN];
bool dp[MAXN],q[MAXN];

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n+m==0)
            break;
        memset(dp,0,sizeof(dp));
        memset(q,0,sizeof(q));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
        dp[0]=1;
        for(int i=1;i<=n;i++)
        {
            if(c[i]==1)
            {
                for(int j=m;j>=a[i];j--)
                    if(dp[j-a[i]])
                        dp[j]=1;
            }
            else if(a[i]*c[i]>=m)
            {
                for(int j=a[i];j<=m;j++)
                    if(dp[j-a[i]])
                        dp[j]=1;
            }
            else
            {
                for(int j=0;j<a[i];j++)//列举每个余下来的
                {
                    int sum=0,st=0,en=-1;
                    for(int v=j;v<=m;v+=a[i])//这边显然是从这个余下来的数 然后去放物品
                    {
                        if(en-st==c[i])//物品数超过了
                            sum-=q[st++];
                        q[++en]=dp[v];//进去
                        sum+=dp[v];    //里面个数
                        if(sum)       //显然要里面有满足条件的  恰好这个或者前面有满足的
                            dp[v]=1;
                    }
                }

            }
        }
        int cnt=0;
        for(int i=1;i<=m;i++)
            if(dp[i])
                cnt++;
        printf("%d\n",cnt);
    }
    return 0;
}

     

时间: 2024-10-27 12:43:48

poj 1742 背包的相关文章

POJ 1742 Coins (多重背包)

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 28448   Accepted: 9645 Description 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

POJ 1742 Coins 多重背包单调队列优化

http://poj.org/problem?id=1742 题意: 很多硬币,有价值和数量,给出一个上限,问上限内有多少种钱数可以由这些硬币组成. 分析: 好像是楼教主男人八题之一.然后学多重背包单调队列优化时看了别人的程序..所以后来写了就1A了=.= 前一篇小小总结了一下多重背包单调队列优化(http://www.cnblogs.com/james47/p/3894772.html),这里就不写了. 1 #include<cstdio> 2 #include<cstring>

Coins POJ - 1742 (背包判断可行性)

 题目链接:  POJ - 1742 题目大意: n个货币,每个货币有一定的数量,然后问你从1~m有多少个数能被凑出来? 具体思路: dp[i][j]代表前i个凑出j元钱第i个的最大剩余量. 二维(超内存): 1 #include<iostream> 2 #include<cstring> 3 #include<stdio.h> 4 using namespace std; 5 # define ll long long 6 # define lson l,mid,rt

hdu 2844 poj 1742 Coins

hdu 2844 poj 1742 Coins 题目相同,但是时限不同,原本上面的多重背包我初始化为0,f[0] = 1;用位或进行优化,f[i]=1表示可以兑成i,0表示不能. 在poj上运行时间正好为时限3000ms....太慢了,hdu直接TLE(时限1s); 之 后发现其实并不是算法的问题,而是库函数的效率没有关注到.我是使用fill()按量初始化的,但是由于memset()可能是系统底层使用了四个字节拷 贝的函数(远比循环初始化快),效率要高得多..这就是为什么一直TLE的原因,fil

[POJ 1742] Coins 【DP】

题目链接:POJ - 1742 题目大意 现有 n 种不同的硬币,每种的面值为 Vi ,数量为 Ni ,问使用这些硬币共能凑出 [1,m] 范围内的多少种面值. 题目分析 使用一种 O(nm) 的 DP (据说这是类多重背包?),枚举每一种硬币,对于每一种硬币 i 枚举每一个面值 j ,如果这个面值 j 使用前 i-1 种硬币已经可以凑出,就直接跳过,否则尝试加入一个硬币 i ,看是否能凑出 j .需要满足 (f[j - Vi] == true) && (UseNum[j - Vi] +

poj 1742 Coins (多重背包)

http://poj.org/problem?id=1742 n个硬币,面值分别是A1...An,对应的数量分别是C1....Cn.用这些硬币组合起来能得到多少种面值不超过m的方案. 多重背包,不过这题很容易超时,用背包九讲的代码有人说行,但是我提交还是超时,后来参考别人代码加了一些优化才能过,有时间要去搞清楚多重背包的单调队列优化. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using

多重背包——POJ 1742

对应POJ题目:点击打开链接 Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 30387   Accepted: 10325 Description 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

POJ 1742 Coins ( 经典多重部分和问题 &amp;&amp; DP || 多重背包 )

题意 : 有 n 种面额的硬币,给出各种面额硬币的数量和和面额数,求最多能搭配出几种不超过 m 的金额? 分析 : 这题可用多重背包来解,但这里不讨论这种做法. 如果之前有接触过背包DP的可以自然想到DP数组的定义 ==> dp[i][j] 表示使用前 i 种硬币是否可以凑成面额 j . 根据这样的定义,则一开始初始化 dp[0][0] = true 最后统计 dp[n][1 ~ m] 为 true 的数量即为答案 状态转移方程为 dp[i][j] |= dp[i-1][ j - k*val[i

POJ 1742 Coins 【多重背包DP】

题意:有n种面额的硬币.面额.个数分别为A_i.C_i,求最多能搭配出几种不超过m的金额? 思路:dp[j]就是总数为j的价值是否已经有了这种方法,如果现在没有,那么我们就一个个硬币去尝试直到有,这种价值方法有了的话,那么就是总方法数加1.多重背包可行性问题 传统多重背包三重循环会超时,因为只考虑是否可行,没有考虑剩余面额数量的因素. o(n*v)方法 #include <iostream> #include <cstdio> #include <string.h> #