回溯法解決裝箱問題

題目描述

有一個箱子容量爲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題

思路

本題可以採用動態規劃進行求解,也可以採用回溯法,分支限界法求解。
這裏我才用回溯法進行求解,問題也就是一個子集樹,在所有的物品中選擇最優的集合使得箱子剩餘容量最小。從根節點開始回溯,構建一棵子集樹,時間複雜度爲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

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章