hdu5410(完全背包变形)

这是道完全背包,关键点在于如何处理每种物品,第一次放时,价值为A+B,以后放时,价值为A。

所以有三种决策,对于第i种物品,要么不放,要么是作为第一个放,要么是第二个以后放。
作为第一个放时,需要用到上一行的状态,所以需要增加一个状态表示上一行的状态。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn  300000
#define LL long long
using namespace std;
int V[maxn],A[maxn],B[maxn];
int d[maxn]; //d[j]代表容量为j的背包,处理到第i种物品时的最大值
int p[maxn]; //p[j]代表容量为j的背包,处理到上一行物品的最大值
int M,N;
void init()
{
     memset(d,0,sizeof(d));
     memset(p,0,sizeof(p));
}
void solve()
{
    for(int i=1;i<=N;i++)
    {
         for(int j=V[i];j<=M;j++)
        {
            d[j]=max(d[j-V[i]]+A[i],d[j]);  //要么不是第一个放
            d[j]=max(p[j-V[i]]+A[i]+B[i],d[j]); //要么是第一个放
        }
        for(int j=0;j<=M;j++)
        {
            p[j]=d[j];
        }
    }
    int ans=0;
    for(int j=0;j<=M;j++)
        ans=max(ans,d[j]);
    printf("%d
",ans);
}
int main()
{
  //freopen("test.txt","r",stdin);
   int t;
   scanf("%d",&t);
   while(t--)
   {
       init();
      scanf("%d%d",&M,&N);
      for(int i=1;i<=N;i++)
      {
          scanf("%d%d%d",&V[i],&A[i],&B[i]);
      }
      solve();
   }
    return 0;
}
第一次做时陷入了一个误区,就是说d[j]=max(d[j-V[i]]+W[i],d[j]);,我想的是用一个数组来记录容量为j的背包能够取得的最大价值的隐含的序列是否放过i种物品,
如果是第一次放,那么W[i]=A+B,如果是第二次放,那么W[i]=A;
可是没有考虑到对于第i种物品,每种容量都有放0,1,一个以上的权利,

但是这样考虑的话,写的时候,就写成了下面这个样子,如果j-V[i]放过的话,那么j容量就只能不放,或者放2个以上。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn  300000
#define LL long long
using namespace std;
int V[maxn],A[maxn],B[maxn];
int d[maxn];
int M,N;
int visit[maxn];
void init()
{
     memset(d,0,sizeof(d));
}
void solve()
{
    for(int i=1;i<=N;i++)
    {
        memset(visit,0,sizeof(visit));
        int t=0;
         for(int j=V[i];j<=M;j++)
        {
             if( visit[j-V[i]]==0) //如果之前没有放过
             {
                 if(d[j-V[i]]+A[i]+B[i]>=d[j])  //加上A+B
                 {
                     d[j]=d[j-V[i]]+A[i]+B[i];
                      visit[j]=1;
                 }
             }
             else   //如果放过,加上A
             {
                // if(j==M)
                 //   printf("d[j]: %d d[j-V[i]] %d V[i] %d
",d[j],d[j-V[i]],V[i]);
                 if(d[j-V[i]]+A[i]>=d[j])
                 {
                     d[j]=d[j-V[i]]+A[i];
                      visit[j]=1;
                 }
             }
          //  d[j]=max(d[j-V[i]]+A[i]+B[i],d[j]);
          printf("%d ",d[j]);
           t++;
          if(t%5==0)
            printf("
");
        }
    printf("

");
    }
    printf("%d
",d[M-1]);
}
int main()
{
  freopen("test.txt","r",stdin);
   int t;
   scanf("%d",&t);
   while(t--)
   {
       init();
      scanf("%d%d",&M,&N);
      for(int i=1;i<=N;i++)
      {
          scanf("%d%d%d",&V[i],&A[i],&B[i]);
      }
      solve();
   }
    return 0;
}
原文地址:https://www.cnblogs.com/xianbin7/p/4747213.html