分析1 :百度和goole了,都说是完全背包,可是我怎么想都不像,只是循环的形式相似,其本质我认为不是完全背包问题。我以为这更像是枚举。
code:
#include<stdio.h>
#include<string.h>
int main()
{
int s, t;
int n;
int i, j, k;
int a[11], sum[10003];
int max, b[11];
while(scanf("%d", &s) && s)
{
max = 0;
scanf("%d", &t);
while(t--)
{
int i, j;
int p;
scanf("%d", &n);
for(j = 1; j <= n; j++)
scanf("%d", &a[j]);
memset(sum, 0, sizeof(sum));
int tmp;
tmp = 0;
sum[0] = 1;
for(i = 1; i <= s; i++)
{
for(j = tmp; j >= 0; j--)
{
if(sum[j])
{
for(int k = 1; k <= n; k++)
{
sum[j+a[k]] = 1;
}
}
}
tmp += a[n];
}
i = 1;
while(sum[i])i++;
if(max < i)
{
max = i;
for(j = 1; j <= n; j++)
b[j] = a[j];
b[0] = n;
}
else if(max == i && b[0] > n)
{
max = i;
for(j = 1; j <= n; j++)
b[j] = a[j];
b[0] = n;
}
else if(max == i && b[0] == n && b[b[0]] > a[n])
{
max = i;
for(j = 1; j <= n; j++)
b[j] = a[j];
b[0] = n;
}
}
printf("max coverage = %d :", max-1);
for(i = 1; i <= b[0]; i++)
printf(" %d",b[i]);
printf("\n");
}
}
分析2:
今天又重新做了pku1882,确实用完全背包的思想可以做出来,但是比上面的枚举的方法更慢,其中的缘由也很好理解。这也给我一个启示——掌握思想后,要灵活转变。
在这题中,解题的一个要点是用尽可能少的张数凑成最大的值,由此可以写出状态方程:
sum[k] = sum[k] > sum[k-j*a[i]]+j ? sum[k-j*a[i]]+j : sum[k]。
把可能的最大值当做v,sum[i]中存的是邮票的张数。
code:
#include<stdio.h>
#include<string.h>