pku1882 Stamps(http://poj.org/problem?id=1882)(博客搬迁)

来源:互联网 发布:mac air键盘灯不亮 编辑:程序博客网 时间:2024/05/17 03:26

分析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>

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, -1, sizeof(sum));
  int tmp;
  tmp = s*a[n];
  sum[0] = 0;
  for(i = 1; i <= n; i++)     //完全背包思想
  {
   for(j = 1; j <= s; j++)
   {
    for(k = j*a[i]; k <= tmp; k++)
    {
     if(sum[k-j*a[i]] != -1)
     {
      if(sum[k] == -1 || sum[k-j*a[i]]+j <= sum[k])
          if(sum[k-j*a[i]]+j <=s)sum[k] = sum[k-j*a[i]]+j;
     }
    }
   }
  }               //end pack
  i = 1;
  while(sum[i] != -1)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");
}
}