• (转)装箱问题


    Description

    有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<=n<=30),每个物品有一个体积(正整数)。
    要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

    Input

    每个测试文件只包含一组测试数据,每组输入的第一行为一个整数V(0<=V<=20000),表示箱子的容量。
    第二行输入一个整数n(0<=n<=30),表示有n个物品。
    接下来n行,每行输入一个正整数,表示每个物品的体积。

    Output

    对于每组输入数据,输出一个整数,表示箱子剩余的最小空间。

    Sample Input 1

    24
    6
    8
    3
    12
    7
    9
    7

    Sample Output 1

    0

    Sample Input 2

    90
    12
    3
    7
    4
    5
    13
    2
    8
    4
    7
    6
    5
    7
    Sample Output 2

    19

    解题思路:利用动态规划

    我自己一开始的错误思想是用贪心算法,觉得先把最大的存进去,剩余的体积就是最小。题目提供的样例都过了,但是提交的时候却在某个样例错了。后来想了想才知道我这种想法有错误之处,先贴出我自己的错误代码

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 int V,n;
     6 int a[40];
     7 int sum = 0;
     8 int main()
     9 {
    10     cin>>V;
    11     cin>>n;
    12     for(int i = 0 ;i < n ;i++)
    13     {
    14         cin>>a[i];
    15         sum += a[i];
    16     }
    17     if(sum<=V) cout<<V-sum;
    18     else 
    19     if(sum>V)
    20     {
    21         sort(a,a+n);
    22         for(int i = n-1 ;i>=0;i--)
    23         {
    24             V -= a[i];
    25             if(V<0)
    26             {
    27                 V += a[i];
    28                 continue;
    29             }
    30         }
    31         cout<<V;
    32      } 
    33      return 0;
    34      
    35 }

    但是这种的话,后来想了一下,对于该数据正确答案是输出0,但是上述代码输出了1;因为代码先把99存进去了;

    100
    4
    99 98 2 2

    后来看了别人的博客,是利用动态规划

    思路:

    对于每一个物体,都有两种选择-放入或者不放入,所以外层循环可对每个物品进行遍历,而每选择一个物品,定会对大于该物品体积的dp数组元素产生影响,从而还需要一个内层数组对大于该物品体积的dp数组元素进行遍历更新。更新方法为:dp[i] = max{ dp[i] , dp[i - vi]+vi },其中vi为当前物品的体积,max中的dp[i]表示不放入该物体时的解, dp[i - vi]+vi表示放入该物体时的解(i-vi表示给即将放入的物品留出合适的体积,如之前的例子,dp[i-vi]并不一定等于dp[i] - vi),取最大值,即为最优解。需要注意的是,需要先将dp数组中的每一个元素初始化为0。
    对于如何运用 dp[i] = max{ dp[i] , dp[i - vi]+vi },下面举个例子详细说明一下过程。
    原文:https://blog.csdn.net/elma_tww/article/details/86507716

     

    继续进行下去,直到遍历完所有物品。

    主要是思想,代码其实挺简单的,代码如下:

     1 #include<iostream>
     2 #include<cmath>
     3 #include<string.h>
     4 using namespace std;
     5 
     6 
     7 int V,n;
     8 int a[40];
     9 int main()
    10 {
    11     cin>>V;
    12     cin>>n;
    13     int dp[V+1];
    14     memset(dp,0,sizeof(dp)); 
    15     for(int i = 0 ;i < n;i++)
    16     {
    17         cin>>a[i];
    18         for(int j = V;j >= a[i];j--)
    19         {
    20             dp[j] = max(dp[j],dp[j-a[i]]+a[i]);
    21         }
    22     }
    23     cout<<V-dp[V];
    24     return 0;
    25 }
  • 相关阅读:
    「SOL」开关(LOJ)
    「SOL」星际迷航(LOJ)
    「NOTE」概率生成函数
    「SOL」谢特(LOJ)
    「SOL」重建计划(BZOJ)
    「SOL」Tug of War(洛谷)
    「SOL」同余方程(LOJ)
    「SOL」Bad Cryptography(Codeforces)
    「SOL」小A与两位神仙(洛谷)
    「SOL」Social Distance(AtCoder)
  • 原文地址:https://www.cnblogs.com/yewanting/p/10539576.html
Copyright © 2020-2023  润新知