算法训练 装箱问题(贪心,动态规划,蓝桥杯,C++)

算法训练 装箱问题

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
  要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
  第一行为一个整数,表示箱子容量;
  第二行为一个整数,表示有n个物品;
  接下来n行,每行一个整数表示这n个物品的各自体积。
输出格式
  一个整数,表示箱子剩余空间。
  样例输入
  24
  6
  8
  3
  12
  7
  9
  7
样例输出
0

思路与解析:

1、虽然题干提示这是一道动态规划,但显然这是一道比较简单基础的贪心,首先我们考虑这道题时要分析到如何能让剩余的空间最小,那么你就会想到尽可能装大的物品,装的大,才是最贪的,剩下的空间一定会很小,那我们初期思路就可以时先把物品的重量排序:(STL真好用)

	#include<algorithm>
	
	sort(&a[0],&a[n]);

2、比如说我们这时容量为10,4个物品,分别为2,3,1,4,那么sort之后数组就变成了1 2 3 4,然后我们可以从后(n-1)往前(0)开始遍历,满足条件如果物品小于容量,那么容量就减去物品大小:

for(int i =n - 1 ;i >= 0;i--)
    {
    
    
        if(box >= a[i])
        {
    
    
            box -= a[i];
        }
    }

※正当我兴高采烈的提交代码时,样例却只给了我80分(不得不说数据真的很水,要不然40都得不到)

这时开始思考有没有特殊的情况没有考虑到?

比如:容量为10 , 5个物品,分别为1 2 3 4 5,那么如果从后往前看的话,先装5,再装4,就已经不能再装了,剩余空间为1,但是我们肉眼能判断 1 + 2 + 3 + 4 == 10,应该装法是 4 3 2 1才对,那么这时思路就要改变,算法要从O(n)变成O(n²),因为第一个装的物品不同的情况下,最后剩余的空间也不同,那么就要遍历每一种情况开头时候他的剩余空间,然后取这些剩余空间的最小值就好啦!

int ans = box;					//答案最初等于箱子的容量
for(int i =n - 1 ;i >= 0;i--)	//i是第一个装的物品
    {
    
    
        min_val = box;			//每一次最小值要重置为箱子初始的容量
        for(int j = i ;j>= 0;j-- ) //第一个是i的情况下,向前遍历
        {
    
    
               if(min_val >= a[j])	//如果容量比物品大,那就装!
                {
    
    
                   min_val -= a[j];	//减去物品
                }
        }
        ans = min(ans,min_val);	//在答案和每次剩余容量中取最小值
    }

3、本题可能用到了dp,但是我暂时还没有去想,大家可以看看其他大佬的代码和思路

最后附上完整AC代码:

#include <stdio.h>
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    
    
    int box,n,min_val;
	int a[32];          ///装物品
	cin >> box >> n;
	int ans = box;
	for(int i = 0;i < n; i++)
    {
    
    
        cin >> a[i];
    }
    sort(&a[0],&a[n]);

    for(int i =n - 1 ;i >= 0;i--)
    {
    
    
        min_val = box;
        for(int j = i ;j>= 0;j-- )
        {
    
    
               if(min_val >= a[j])
                {
    
    
                   min_val -= a[j];
                }
        }
        ans = min(ans,min_val);
    }
    cout << ans;
	return 0;
}

后语:本人一般比较喜欢更简洁的算法思想,平常一般看到其他大佬的简洁代码不仅感叹,所以代码总体来说都比较短,喜欢把这种高效率的算法分享给大家,本题若有更好的算法还请一起交流!

猜你喜欢

转载自blog.csdn.net/Kyrie_irving_kun/article/details/113638715