題目描述
有一個箱子容量爲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;
}