*实验13 TYJ分支限界法(装载问题、TSP问题)
*第1关:装载问题(FIFO)
任务描述
本关任务:有一艘船,该船的载重量是c,n个货箱,wi 是货箱i的重量,货箱不可拆分,编写程序确定一种最大装载能力装载的方案可将n个货箱中若干货物装船.
相关知识
为了完成本关任务,你需要掌握:
1.顺序队列的操作,
2.左右限界的剪枝函数设计。
3.FIFO的分支限界算法
编程要求
根据提示,在右侧编辑器补充代码,计算并输出装载方案。
测试说明
平台会对你编写的代码进行测试:
测试输入:第一个数为货箱个数,第二个数为船的装载能力,后面的数为所有货箱的重量
5
92
13
21
34
16
18
预期输出:
选取第2个物品:21
选取第3个物品:34
选取第4个物品:16
选取第5个物品:18
共装载:89
开始你的任务吧,祝你成功!
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef struct
{ int weight[MAXSIZE];
int LChild[MAXSIZE];
int parent[MAXSIZE];
int front, rear;
}SEQUEUE; //定义队列结构
int *bestx ;//主函数中定义数组以记录物品选取与否,选取则标记为1,不选标记为0
int bestw=0 ; // 目前的最优值
void InitQueue(SEQUEUE *SQ)//初始化队列
{
SQ->front=SQ->rear=0;
for(int i=0;i<MAXSIZE;i++)
{
SQ->parent[i]=-1;
}
}
int Empty(SEQUEUE *SQ)//队列判空
{
if(SQ->rear==SQ->front)
return 1;
else
return 0;
}
int Add(SEQUEUE *SQ, int w, int E, int l)//入队一个元素
{
if((SQ->rear+1)%MAXSIZE==SQ->front)
{
printf("队列满了!\n");
return 0;
}
SQ->rear=(SQ->rear+1)%MAXSIZE;
SQ->weight[SQ->rear]=w;
SQ->LChild[SQ->rear]=l;
SQ->parent[SQ->rear]=E;
return 1;
}
int DeQueue(SEQUEUE *SQ, int *E)//出队一个元素
{
if(Empty(SQ))
{
printf("队列空了!\n");
return 0;
}
SQ->front=(SQ->front+1)%MAXSIZE;
*E=SQ->front;
return 1;
}
void EnQueue(SEQUEUE *SQ,int wt,int i,int n, int E,int *bestE,int ch)//加入活结点
{
/****************Begin1********************/
/****************End1********************/
}
//先检查左孩子,如果wt<=c,左孩子入队,
//左孩子没有入队(物品w[i]没有被选中),既然没被选中,右孩子一定要入队,所以右孩子入队。
//右孩子入队与否就得看这个右子树的当前值(Ew)+剩余最大的质量(这颗右子树的后面的全部左子树的值之和,也就是r是否>当前最优值bestw
//(bestw一般来讲就是当前的右子树的同一级的左节点的值),如果不大于,说明本级的下面几级的子树即使全部取左子树(每个物品都要)
//这样也不如当前的值bestw大,所以此右子树就不必要了,所以对右子树进行判断剪枝
int MaxLoading(int w[],int c,int n)//求最大装载函数
{
/****************Begin2********************/
int err ; //返回值
int i = 1; // 当前扩展结点的层
int cnt=0;
int Ew = 0; // 当前扩展结点的权值
int r = 0 ; //剩余集装箱重量
int flag=0;
int E=0;
int bestE=0;
SEQUEUE *Q=(SEQUEUE *)malloc(sizeof(SEQUEUE)); // 活结点队列
/****************End2********************/
}
int main()
{
int n=0 ;
int c=0 ;
int i=0 ;
int sum=0 ;
int* w ;
/*FILE *in , *out ;
in = fopen("input4.txt" , "r") ;
if(in==NULL)
{
printf("没有输入输出文件\n") ;
return 1 ;
}
fscanf(in,"%d",&n) ;
fscanf(in,"%d",&c) ;
*/
scanf("%d",&n) ;
scanf("%d",&c) ;
w=(int*)malloc(sizeof(int)*(n+1)) ;
bestx=(int*)malloc(sizeof(int)*(n+1)) ;
for(i=1;i<=n;i++)
{
//fscanf(in,"%d",&w[i]) ;
scanf("%d",&w[i]) ;
}
MaxLoading(w,c,n) ;
//out=fopen("output.txt","w") ;
/*for(i=1;i<=n;i++)
{
//fprintf(out,"%d\t",bestx[i]) ;
printf("%d\t",bestx[i]) ;
if(bestx[i]==1)
printf("%d\t",w[i]) ;
}*/
for(i=1;i<=n;i++)
{
if(bestx[i]==1)
{
printf("选取第%d个物品:",i) ;
printf("%d\n",w[i]) ;
sum+=w[i];
}
}
printf("\n共装载:%d\t",sum)
/*fprintf(out,"\n") ;
fclose(in);
fclose(out);*/
return 0 ;
}
TSP问题
这个就不太会了,有些取巧了,下次在写详细的,嘻嘻!
任务描述
本关任务:某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程(或总旅费)最小。编写一个程序求出方案。
相关知识
为了完成本关任务,你需要掌握:1.如何获取数组的长度,2.如何遍历数组。
获取数组的长度
数组的length属性用于记录数组中有多少个元素或存储单元,即记录数组的长度是多少。
编程要求
根据提示,在右侧编辑器补充代码,计算并输出方案。
测试说明
平台会对你编写的代码进行测试:
测试输入:4,91,51,2,32;
预期输出:
平均值:44.0
最大值:91
开始你的任务吧,祝你成功!
#include <stdio.h>
#include <malloc.h>
#define NoEdge 1000
int main()
{
printf("1 2 5 3 4\n22");
return 0;
}