• 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;
    }
  • 相关阅读:
    (转)卡特兰数
    fatal error LNK1123: 转换到 COFF 期间失败
    cocos2dx 中文乱码问题
    c++ primer查漏补缺(一)命名空间
    Centos 7 二进制部署高可用Kubernetes v1.17.x
    hostAliases给pod增加域名解析
    常用的清理 Kubernetes 集群资源命令
    Kubernets 污点与容忍
    Docker 常用命令大全
    Kubernets健康检查——配置存活、就绪和启动探测器
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4747213.html
Copyright © 2020-2023  润新知