zoukankan      html  css  js  c++  java
  • Come to a spring outing BNU 29358

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=29358

    这个题目的话,初看就想到要用背包,一个包一个包的装,装好两个包的话,就可以直接判断了。

    当然中间还有剪枝的部分,代码中有很好的体现,这个怎么说呢,代码写了很多,但是是为了节省时间,比较划来的。

    当然这个问题最重要的不是剪枝,而是背包算法的运用:如何标记第一个背包已经使用过的物品。

    为了标记,我觉得使用二维dp数组比一维数组好,但是标记后的处理也十分重要,详见代码。

    此处本人还耍了一点小聪明,标记的话,第二次读的时候n和整个数组都变了,突发奇想,把标记了的物品体积赋值为0.这样就不会影响其它的背包了。

    代码如下:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define M 450
      6 #define mem0(f) memset(f,0,sizeof(f))
      7 int t;
      8 int n,c;
      9 int v[M];
     10 int dp[M][M];//二维背包数组
     11 int vis[M][M];//表示第i个物品在构成j时是否被选用
     12 int s;
     13 int ok;
     14 int biaoji[M];
     15 int main()
     16 {
     17     scanf("%d",&t);
     18     for(int tt=1;tt<=t;tt++)
     19     {
     20         ok=1;
     21         scanf("%d%d",&n,&c);
     22         s=0;
     23         mem0(v);
     24 
     25         for(int i=1;i<=n;i++)//用二维数组的话,一定要从1开始存入
     26         {
     27             scanf("%d",&v[i]);
     28             if(v[i]>c)
     29             {
     30                 ok=0;
     31             }
     32             s+=v[i];
     33         }
     34         if(s>3*c)ok=0;
     35         if(ok==0)
     36         {
     37             printf("Case %d: No
    ",tt);
     38             continue;
     39         }
     40         int p=2;
     41        // mem0(dp);
     42        mem0(biaoji);
     43         while(p--)
     44         {
     45         mem0(vis);
     46         mem0(dp);
     47         for(int i=1;i<=n;i++)
     48         {
     49             //if(biaoji[i])continue;
     50             for(int k=c;k>=0;k--)
     51             {
     52                 //
     53                 if(k>=v[i])
     54                 {
     55                 if(dp[i-1][k]>dp[i-1][k-v[i]]+v[i])
     56                 {
     57                     dp[i][k]=dp[i-1][k];
     58                     vis[i][k]=0;
     59                 }
     60                 else
     61                 {
     62                     dp[i][k]=dp[i-1][k-v[i]]+v[i];
     63                     vis[i][k]=1;
     64                 }
     65                 }
     66                 else
     67                 {
     68                     dp[i][k]=dp[i-1][k];
     69                     vis[i][k]=0;
     70                 }
     71             }
     72         }
     73        // printf("tttttttttt%d
    ",dp[n][c]);
     74         //第一个背包
     75 
     76         if(p==1&&dp[n][c]<(double)s/3)//剪枝
     77         {
     78             printf("Case %d: No
    ",tt);
     79             break;
     80         }
     81         s-=dp[n][c];
     82         if(p==0&&dp[n][c]<(double)s/2)//剪枝
     83         {
     84             printf("Case %d: No
    ",tt);
     85             break;
     86         }
     87 
     88         if(p==0)
     89         {
     90             s<=c;
     91             printf("Case %d: Yes
    ",tt);
     92             break;
     93         }
     94         if(s<=0)
     95         {
     96             printf("Case %d: Yes
    ",tt);
     97             break;
     98         }
     99         int pt=0,vv=c;
    100         for(int i=n;i>=1;i--)
    101         {
    102             if(!vis[i][vv])
    103             {
    104                 biaoji[i]=0;
    105                 //v[i]=0;
    106             }
    107                 else
    108             {
    109                 biaoji[i]=1;vv=vv-v[i];
    110                 v[i]=0;//把装过了的值赋为0
    111             }
    112 
    113         }
    114         }
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    二叉树学习随笔
    结构体初始化中的数组赋值
    C和FORTRAN的快速傅里叶/余弦/正弦变换(Fast Fourier/Cosine/Sine Transform)开源库分享
    Java简单的数组用法尝试,和C语言很不一样
    中位数( 优先队列较优处理 )
    单调队列 数组写法qwq
    P1886 滑动窗口
    Sicily 2014. Dairy Queen
    P3385 【模板】负环
    [USACO06DEC]虫洞Wormholes (负环模板)
  • 原文地址:https://www.cnblogs.com/plank-george-zzo/p/3280078.html
Copyright © 2011-2022 走看看