#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50;
int s,n,t;
int a[maxn][maxn];
int dp[1500][maxn];
int stamp(int set,int c,int n)
{
if(dp[c][n]!=-1)
return dp[c][n];
if(!c)
{
dp[c][n]=1;
return 1;
}
if(!n)
{
dp[c][n]=0;
return 0;
}
for(int i=1;i<=a[set][0];i++)//循环加深搜解决此类类似组合求解值的问题像DAG问题和书上的硬币模型类似
{
if(c>=a[set][i]&&stamp(set,c-a[set][i],n-1))
{
dp[c][n]=1;
return 1;
}
}
dp[c][n]=0;
return 0;
}
int cmp(int x,int y)
{
if(a[x][0]<a[y][0]) return x;
if(a[x][0]>a[y][0]) return y;
for(int i=a[x][0];i>0;i--)
{
if(a[x][i]<a[y][i]) return x;
if(a[y][i]<a[x][i]) return y;
}
return x;
}
int main()
{
while(scanf("%d",&s)!=EOF)
{
if(s==0)
break;
int key=0;
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i][0]);
for(int j=1;j<=a[i][0];j++)
scanf("%d",&a[i][j]);
}
for(int i=1;i<=n;i++)//从n组的邮票集里选哪一组进行求值
{
memset(dp,-1,sizeof(dp));//求新一组的值之前进行dp初始化
int k=0;
for(int j=1;;j++)//j为当前最大的邮资值
{
if(stamp(i,j,s))//进入函数看看该邮资j能否由得当前组的邮票组成
k=j;
else
break;
}
if(k==ans)
key=cmp(key,i);
if(k>ans)
{
ans=k;
key=i;
}
}
printf("max coverage =%4d :",ans);
for(int i=1;i<=a[key][0];i++)
printf("%3d",a[key][i]);
printf("\n");
}
return 0;
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
http://blog.csdn.net/squee_spoon/article/details/38014425