【poj3093】Margaritas on the River Walk

题目描述

N件物品和一个体积是C的背包。需要把一些物品装到背包里使得剩下的物品无法再放入,求方案数。每件物品有一个体积Vi。


输入

本题包含多组测试数据。第一行输入一个整数,表示数据组数。接下来对于每组数据的第一行是两个整数,N,C。然后N个整数Vi,表示每个物品的体积,1<=C<=1000,1<=N<=30。


输出

对于每个测试数据,输出2个整数,第一个表示数据编号,第二个是题目要求的方案数。


样例输入

2

6 25

8 9 8 7 16 5

30 250

1 2 3 4 5 6 7 8 9 10 11

12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30


样例输出

1 15

2 16509438

 


 


题解

01背包变种题。

 

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=30+20;
const int maxv=1000+5;

int T,n,m,v[maxn],sum[maxn],dp[maxv],Case=1;

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
    read(T);
    while(T--){
        read(n),read(m);
        for(int i=0;i<=m;i++) dp[i]=0;
        for(int i=1;i<=n;i++) read(v[i]);
        sort(v+1,v+1+n);
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+v[i];
        if(v[1]>m){
            cout<<Case++<<" "<<"0"<<endl;
            continue;
        }
        int ans=0;dp[0]=1;
        for(int i=n;i>=1;i--){
            int left=m-sum[i-1];
            for(int j=max(0,left-v[i]+1);j<=left;j++) ans+=dp[j];
            for(int j=m;j>=v[i];j--) dp[j]+=dp[j-v[i]];
        }
        cout<<Case++<<" "<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-08-19 08:46  rld  阅读(114)  评论(0编辑  收藏  举报