题意:有n件物品,每件都有价值,用m的钱买这些物品,。尽可能多的买东西,(直到钱不够买其他的东西为止)。问有多少种买东西的方法。。
思路:自己弄了一个状态转移方程,发现是错的。。后来 yy教我的‘。。。。先不买第一件物品,弄一个方程。。。再必须买第一件物品,不用第二件物品。。。再必须买前两件,不买第三件。。。类推。。这样就没有重复。。。然后考虑边界就ok了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
int n,m;
int dp[1009],re[39];
void solve(int c,int s)
{
memset(dp,0,sizeof(dp));dp[0]=1;
for(int i=c;i<n;i++)
{
for(int j=s-re[i];j>=0;j--)
if(dp[j]) dp[j+re[i]]+=dp[j];
}
}
int main()
{
freopen("in.txt","r",stdin);
int cas,T = 1,s;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);s=0;
for(int i=0;i<n;i++)
scanf("%d",&re[i]),s+=re[i];
sort(re,re+n);
if(s<=m){
printf("%d 1\n",T++);continue;
}else if(re[0]>m){
printf("%d 0\n",T++);continue;
}
int ans=0,ad=0;
for(int i=0;i<n;i++)
{
solve(i+1,m-ad);
for(int j=max(0,m-ad-re[i]+1);j<=(m-ad);j++)
ans+=dp[j];
ad+=re[i];
}
printf("%d %d\n",T++,ans);
}
return 0;
}