早期西工大机试 背包和船装载
0-1背包问题
问题描述
给定一组有固定价值和固定重量的物品,以及一个已知最大承重量的背包,求在不超过背包最大承重量的前提下,能放进背包里面的物品的最大总价值。
思路
该问题的解决思路是动态规划,为减少递归的重复计算,定义一个二维数组B[N] [C]保存计算过的值,B[i] [j] 表示前i件物品放入容量为j的背包中所能获得的最大价值
如果只考虑第i件物品的放与不放,那么问题就转化为一个比较简单的形式:
(1) 当第i件物品太大,放不进去 ,则最大价值为前i-1件物品放入容量为j的背包,即B[i] [j] =B[i-1] [j] ,
(2)当第i件物品可以放入,不放入这件物品的价值是前i-1件物品放入容量为j的背包所能获得的最大价 值,放入这件物品的价值是前i-1件物品放入容量为当前背包容量减去这个物品重量的背包中的最 大价值加上这个物品的价值,取这两者的的最大价值:
即B[i] [j]=max{B[i-1] [j], B[i-1] [j-weight[i]]+value[i]}
代码
#include <stdio.h>
#include <stdlib.h>
#define N 6
#define C 30
int value[N+1]={0,2,4,6,8,10,12};
int weight[N+1]={0,2,4,6,8,10,12};
int B[N+1][C+1];
void knapsack()
{
int i,j;
for(i=1;i<=N;i++){
for(j=1;j<=C;j++){
if(weight[i]>j)
B[i][j]=B[i-1][j];
else{
int value1=B[i-1][j];
int value2=B[i-1][j-weight[i]]+value[i];
B[i][j]=value1>value2?value1:value2;
}
}
}
}
int main()
{
knapsack();
printf("%d\n",B[N][C]);
return 0;
}
船装载问题
问题描述
有两艘船,载重量分别是c1、 c2,n个集装箱,重量是wi (i=1…n),且所有集装箱的总重量不超过c1+c2。确定是否有可能将所有集装箱全部装入两艘船。
思路
采用贪心的思想解决该问题,先尽可能的把第一艘船装满,然后看剩下的货物的能不能装进第二艘船
把货物装入第一艘船时采用递归的方式,不断回溯得到最大重量
只看第i个物品装不装
case 1:如果装不下第i件物品,就舍弃,考虑下面的货物是否装入
case 2:如果第i件物品可以装入,(1)更新最大重量,递归装入下面的物品,计算出装入i的最大重量 (2)不装入i,计算最大重量 (3)函数返回时比较(1)(2),取最大值
代码
#include <stdio.h>
#include <stdlib.h>
#define N 9
#define C1 50
#define C2 40
int w[N+1]={0,1,2,4,6,8,10,12,20,30};
int bestweight=0;
int weight=0;
int load(int x){
if(x==N){
if(weight>bestweight)
weight=bestweight;
return bestweight;
}
else{
if(w[x]+weight<=C1){
weight+=w[x];
load(x+1);
weight-=w[x];
}
load(x+1);
}
}
int main(){
int i,total=0;
for(i=1;i<=9;i++)
total+=w[i];
load(1);
if(C2>=total-bestweight)
printf("Yes");
else
printf("No");
return 0;
}