D14439. 【NOIP2001P】装箱问题
时间限制:1.0s 内存限制:256.0MB 代码提交间隔:1分钟(现在可以提交)
输入文件名:park.in 输出文件名:park.out
试题来源:NOIP
问题描述
有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0≤n≤30,每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
一个整数,表示箱子容量
一个整数,表示有n个物品
接下来n行,分别表示这n 个物品的各自体积
输出格式
一个整数,表示箱子剩余空间。
样例输入
24
6
8
3
12
7
9
7
样例输出
0
思路:
定义f(v,n)为用n个物品填充V体积,该物品有选f(v-w[k],k-1)和不选f(v,k-1)两种情况,当n为零或是v<=0时为边界。
f(V,N)= Min(f(v-w[k],k-1),f(v,k-1))
v (k=0)
0 (v=0)
Code:
递归:
#include<bits/stdc++.h> using namespace std; int v,n; int w[40]; int dp[20010][40]; int park(int vs,int k){ if (vs < 0) return vs + w[k+1];//科科因为最后一句没有比较当前容积和选中物品体积所以此处加判一句 if (vs == 0) return 0; if (k == 0) return vs; if (dp[vs][k]) return dp[vs][k]; return dp[vs][k] = min(park(vs - w[k],k - 1),park(vs,k - 1)); } int main(){ freopen("park.in","r",stdin); freopen("park.out","w",stdout); cin >> v >> n; for (int i = 1; i <= n; i++) cin >> w[i]; int ans = park(v,n); cout << ans << endl; return 0; }
当然可以递推求解。
Code:
递推:
#include<bits/stdc++.h> using namespace std; int v,n; int w[40],vs[20010]; int main(){ freopen("park.in","r",stdin); freopen("park.out","w",stdout); cin >> v >> n; for (int i = 1; i <= n; i++) cin >> w[i]; for (int i = 1; i <= n; i++){ for (int j = v; j >= w[i]; j--) vs[j] = max(vs[j],vs[ j-w[i] ] + w[i]); }//递推过程,本质上是背包问题 int maxv = -1; for (int i = 1; i <= v; i++) maxv = max(maxv,vs[i]); cout << v - maxv << endl; }