0-1背包:问题描述,NOIP 2001 装箱问题
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
剩下最少的体积。
s[v]表示容积为v的箱子,最多能装的物品体积
则对当前的物品m,动态转移方程:
s[v]=max{ s[v],s[v-w[m]]+w[m] }
实现:
for(i=0;i<n;i++)
{
for(j=v;j>=w[i];j--)
if(s[j-w[i]]+w[i]>s[j])
s[j]=s[j-w[i]]+w[i];
}
深度搜索考虑:
深度搜索:以一个点为起点,向下搜索,直到末尾节点为止。但是要注意,搜索中节点回溯(即某个节点,在搜索的过程中,可以添加,也可以不添加的情况处理)
#include <stdio.h>
#include <stdlib.h>
/*
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,
每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
这是一个典型的0—1背包型问题,可以采用搜索(深搜)、动态规划等方法
深度搜索:以一个点为起点,向下搜索,直到末尾节点为止。但是要注意,搜索中节点回溯
(即某个节点,在搜索的过程中,可以添加,也可以不添加的情况处理)
*/
int V,n,w[31],min;
int dfs(int k,int v) //深度搜索
{
if(k>=n||v<=0) return 0; //搜索结束的情况
int i,j;
for(i=k;i<n;i++) //分别在[k,n]区间内,以各个点为起点,向下深搜
{
if(v-w[i]>=0) //该节点在限制范围内可以添加
{
if(v-w[i]<min) min=v-w[i]; //将该节点添加进来
// printf("min=%d\n",min);
v=v-w[i];
dfs(i+1,v); //继续搜索下一位置的节点
//注意,搜索完后需要回溯处理,因为当前的i节点是(取或不取)两种情况都考虑
//前面部分是取了该节点,向下搜索,接下来V的值回溯,不取该节点,继续下搜索
v=v+w[i];
// printf("v=%d\n");
}
}
return 0;
}
int main(int argc, char *argv[]) {
int i,j;
freopen("npack.in","r",stdin);
freopen("npack.out","w",stdout);
scanf("%d%d",&V,&n);
for(i=0;i<n;i++) scanf("%d",&w[i]);
min=V;
dfs(0,V);
printf("%d\n",min);
return 0;
}