读入水桶种类后,先对其容量从小到大排序,然后从选1个水桶到选p个水桶枚举,dfs迭代搜索。dfs(i,j)表示剩下i个水桶,从j号水桶开始向下搜索(这样可以减少复杂度,迭代的思想,避免重复计算)。安排上某个水桶就给它打标记,用这个标记写dp判断现有水桶能否组合成答案。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
int p,v;
bool b[110];
int dp[20010];
int a[110];
int maxm;
bool dg()
{
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=p;i++)
if(b[i])
for(int j=a[i];j<=v;j++)
if(dp[j-a[i]]==1) dp[j]=1;
return dp[v];
}
void dfs(int rest,int st)
{
if(rest==0)
{
if(dg())
{
cout<<maxm<<' ';
for(int i=1;i<=p;i++)
{
if(b[i]) cout<<a[i]<<' ';
}
exit(0);
}
else
return ;
}
if(p-st+1>=rest)
{
for(int i=st;i<=p;i++)
{
if(b[i]==false)
{
b[i]=true;
dfs(rest-1,i+1);
b[i]=false;
}
}
}
}
int main()
{
scanf("%d%d",&v,&p);
for(int i=1;i<=p;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+p+1);
for(int i=1;i<=p;i++)
{
memset(b,0,sizeof(b));
maxm=i;
dfs(i,1);
}
return 0;
}