【问题描述】
给定n个货箱,货箱i 重为 wi, 船可以装载的货箱总重量为 W。 货箱装载问题是在不超过载重量的前提下装载尽可能重的货箱。
装载问题的解可以用向量 (x1,x2,…,xn)表示,xi∈{0,1}, xi =1 表示货箱i被装上船, xi =0表示货箱 i不装上船。请设计一个基于回溯算法的装载问题的求解方案。
【输入】
第1行输入正整数n和船的装载重量W,第2行依次输入n个整数,表示n个货箱的重量。
【输出】
输出两行,第1行输出最大的装载重量,第2行输出解向量 (x1,x2,…,xn)。
【输入样例】
6 26
1 7 4 20 9 11
【输出样例】
25
1 0 1 1 0 0
static int[] x = new int[w.length];
static int[] bestx = new int[w.length];
static int bestw = Integer.MIN_VALUE;
static int cw = 0;
static int r = 0; // 记录物品i后面所有物品的总重量
public static void main(String[] args) {
for (int i = 0; i < w.length; i++) {
r += w[i];
}
backstrace(0);
int sum = 0;
for (int i = 0; i < bestx.length; i++) {
if(bestx[i] == 0){
sum += w[i];
}
}
if(sum > c2){
System.out.println("物品无法装载到轮船!");
return;
}
System.out.println("C1:" + c1 + "装载物品:");
for (int i = 0; i < bestx.length; i++) {
if(bestx[i] == 1){
System.out.print(w[i] + " ");
}
}
System.out.println();
System.out.println("C2:" + c2 + "装载物品:");
for (int i = 0; i < bestx.length; i++) {
if(bestx[i] == 0){
System.out.print(w[i] + " ");
}
}
System.out.println();
}
private static void backstrace(int i) {
if(i == w.length){
if(cw > bestw){
bestw = cw;
for (int j = 0; j < x.length; j++) {
bestx[j] = x[j];
}
}
} else {
r -= w[i];
if(cw + w[i] <= c1){
cw += w[i];
x[i] = 1;
backstrace(i+1); // 选择第i个节点
cw -= w[i];
}
if(cw + r > bestw){
x[i] = 0; // 才有必要去往右边的i节点
backstrace(i+1); // 没选择第i个节点
}
r += w[i];
}
}
运行结果:
挺有意思的一类算法问题,待我研究研究
#include <stdio.h>
#include <stdlib.h>
int * Loading(int c1,int w[],int n);// 返回最优解
void Backtrack(int* i,int *B,int *w,int *x);// 回溯
// record the best result
void record(int *rec,int *x,int n);// 记录最优解
void sort(int *num,int n);// 冒泡排序由大到小
int main()
{
// 未按照顺序简历
int W[7]={30,20,12,10,90,80,40};
int c1=152,c2=130;
int *res=Loading(c1,W,7);
// 输出结果方案
for(int i=0; i<7; i++)
printf("%d\t",res[i]);b2
return 0;
}
int * Loading(int c1,int w[],int n){
sort(w,n);// 将载重量由大到小排序
// x[i]表示第i个集装箱是否装入第一艘船
// rec记录最优解
int *x=(int*)malloc(n*sizeof(int));
if(x==NULL) exit(0);
int *rec=(int*)malloc(n*sizeof(int));
if(rec==NULL) exit(0);
for(int i=0; i<n; i++){
x[i]=0;
rec[i]=0;
}
// B表示当前第一艘船剩余载重空间,best表示最小的剩余载重空间
// 求得best最小值即为求得使第一艘船载重最多的情况
int B=c1,best=c1,i=0;
do{
while(i<n){
// 如果装入后重量不超过C1
if(B-w[i]>=0){
B=B-w[i];
x[i]=1;
}else{
x[i] = 0;
}
i++;
}
if(B<best){
// 记录此时最优解
record(rec,x,n);
best=B;
}
// 回溯到可以分支的支点上
Backtrack(&i,&B,w,x);
}while(i!=0);
return rec;
}
void Backtrack(int* i,int *B,int *w,int *x){
while(*i>0 && x[*i]==0) (*i)-=1;
if(x[*i] == 1){
x[*i]=0;
*B+=w[*i];
(*i)++;
}
}
void record(int *rec,int *x,int n){
for(int i=0;i<n;i++)
rec[i]=x[i];
}
void sort(int *num,int n){
// 冒泡排序
int tmp;
for(int i=n-1; i>0; i--)
for(int j=0; j<i; j++){
if(num[j]<num[j+1]){
tmp=num[j];
num[j]=num[j+1];
num[j+1]=tmp;
}
}
}
您的问题已经有小伙伴解答了,请点击【采纳】按钮,采纳帮您提供解决思路的答案,给回答的人一些鼓励哦~~
ps:开通问答VIP,享受5次/月 有问必答服务,了解详情↓↓↓
【电脑端】戳>>> https://vip.csdn.net/askvip?utm_source=1146287632
【APP 】 戳>>> https://mall.csdn.net/item/52471?utm_source=1146287632