zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    数据分析的数据来源都有哪些?
    数据分析的技能要求及分析流程
    (原创)使用matlab-cftools拟合工具的问题
    Spring加载xml配置文件的方式
    Spring-ResolvableType可解决的数据类型
    从list中取N个随机生成一个集合
    AOP统一处理修改人、创建人、修改时间、创建时间
    Java依据集合元素的属性,集合相减
    java去掉数字后面的0
    数字格式化NumberFormat
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4747213.html
Copyright © 2011-2022 走看看