回溯法解决装箱问题

题目描述

有一个箱子容量为V(正整数,0≤V≤200000 ),同时有n个物品(0<n≤300),每个物品有一个体积(正整数)。

要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入格式

1个整数,表示箱子容量

1个整数,表示有n个物品

接下来n行,分别表示这n个物品的各自体积

输出格式

1个整数,表示箱子剩余空间。

输入输出样例

输入

24
6
8
3
12
7
9
7

输出

0

说明/提示

NOIp2001普及组 第4题

扫描二维码关注公众号,回复: 9945762 查看本文章

思路

本题可以采用动态规划进行求解,也可以采用回溯法,分支限界法求解。
这里我才用回溯法进行求解,问题也就是一个子集树,在所有的物品中选择最优的集合使得箱子剩余容量最小。从根节点开始回溯,构建一棵子集树,时间复杂度为O(n2)

代码

#include <iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<math.h>
int w[31];//定义物品重量数组,不超过30个
int bestw;//当前最优值
int cw;//当前箱子放的物品的总重量
void getbestw(int i,int c,int n)
{
    if(i>n){//递归回溯的出口
        if(bestw<cw)
            bestw=cw;//更新最优值
        return;
    }
    for(int k=0;k<=1;k++){//子集问题,要么放,要么不放
        if(cw+k*w[i]<=c){//约束函数,如果满足条件,可以遍历子树
            cw=cw+k*w[i];
            getbestw(i+1,c,n);
            cw=cw-k*w[i];
        }
    }
    return;
}
int main()
{
    int c;
    int n;
    cin>>c>>n;
    for(int i=1;i<=n;i++)
        cin>>w[i];
    getbestw(1,c,n);
    if(c-bestw<=0)//如果当前最优值大于等于箱子容纳量c
        cout<<0;//输出0
    else//输出箱子最小剩余重量
        cout<<c-bestw;
    return 0;
}

AC

在这里插入图片描述

发布了97 篇原创文章 · 获赞 101 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/practical_sharp/article/details/102791252