装箱问题
(pack.pas/c/cpp)
来源:NOIP2001(普及组) 第四题
【问题描述】
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30=,每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
【输入文件】
第一 行一个正整数V表示箱子的容量,第二行一个正整数N表示物品个数,接下来N行列出这N个物品各自的体积。
【输出文件】
单独一行,表示箱子最小的剩余空间。
【输入样例】
24
6
8
3
12
7
9
7
【输出样例】
0
【问题分析】
本题是经典的0/1背包问题,并且是0/1背包的简化版,把箱子看做背包,容量看做载重量,体积看做重量,剩余空间最小也就是尽量装满背包。于是这个问题便成了:
有一个栽重量为V的背包,有N个物品,尽量多装物品,使背包尽量的重。
设计一个状态opt[i]表示重量i可否构成。
状态转移方程:opt[j]:=opt[j-w[1]] {opt[j-w[i]]=true}
最终的解就是v-x(x<=n 且opt[x]=true 且 opt[x+1..n]=false)。
用01背包做
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<vector> 5 #include<set> 6 #include<queue> 7 #include<map> 8 #include<stack> 9 #include<iterator> 10 #include<cstdio> 11 #include<cstring> 12 #include<cstdlib> 13 #include<cmath> 14 using namespace std; 15 typedef long long ll; 16 typedef unsigned long long ull; 17 #define clr(c) memset(c, 0, sizeof(c)); 18 #define pi acos(-1.0) 19 const int INF = 0x3f3f3f3f; 20 const int mod = 1e9 + 7; 21 const double eps = 1e-8; 22 typedef struct point{ 23 int x, y; 24 bool operator < (const point& p) const{ 25 if (x == p.x) return y < p.y; 26 else return x < p.x; 27 } 28 bool operator >(const point& p) const{ 29 return p < *this; 30 } 31 }p; 32 int a[1005]; 33 int dp[1005]; 34 int v, n; 35 36 int main(){ 37 while(~scanf("%d", &v)){ 38 scanf("%d", &n); 39 for(int i = 0; i < n; i++) scanf("%d", &a[i]); 40 memset(dp, 0, sizeof(dp)); 41 for(int i = 0; i < n; i++){ 42 for(int j = v; j >= a[i]; j--){ 43 dp[j] = max(dp[j], dp[j-a[i]]+a[i]); 44 } 45 } 46 printf("%d ", v-dp[v]); 47 } 48 49 return 0; 50 }