贪心算法之装箱问题

装箱问题的贪心准则:

1.将物品体积从大到小排列

2.遍历箱子,将物品放入一个较早打开的且剩余空间足够的箱子,否则开新箱子


结点类型:

typedef struct goodnode{
	int gno;
	int v;
}Goods;   //物品信息结点

typedef struct GoodNode{
	int gno;
	struct GoodNode *next;
}GNode;    //物品链结点

typedef struct BoxNode{
	int reminder;
	GNode *h;
	struct BoxNode *next;
}BNode;    //箱子链结点


排序(这里使用希尔排序)

void Swap(Goods *p,Goods *q){     
	int gno,v;
	gno=p->gno;
	v=p->v;
	p->gno=q->gno;
	p->v=q->v;
	q->gno=gno;
	q->v=v;
	q->gno=gno;
}

void ShellSort(Goods *g,int n){       //物品信息存在数组g中,n为物品个数
	int gap,i,j;
	int tv,tno;
	for(gap=n/2;gap>0;gap/=2){
		for(i=gap;i<n;i++){
			if(g[i].v>g[i-gap].v){
				tv=g[i].v;
				tno=g[i].gno;
				j=i-gap;
				while(j>=0&&g[j].v<tv){
					Swap(g+j+gap,g+j);
					j=j-gap;
				}
				g[j+gap].gno=tno;
				g[j+gap].v=tv;
			}
		}
	}
}


开箱子放物品

BNode* CreateBox(Goods *g,int n,int v){     
	BNode *h,*pb,*t;
	GNode *pg,*p;
	int i;
	h=NULL;
	for(i=0;i<n;i++){
		pg=(GNode*)malloc(sizeof(GNode));     //创建物品链结点
		pg->gno=g[i].gno;
		pg->next=NULL;
		for(pb=h;pb&&pb->reminder<g[i].v;pb=pb->next);   //找到可以放当前物品的箱子,若p==NULL,则表示开新箱子
		if(pb==NULL){                //开新箱子
			pb=(BNode*)malloc(sizeof(BNode));
			pb->h=NULL;
			pb->reminder=v;
			pb->next=NULL;
			if(h==NULL)     //挂箱子链
				t=h=pb;    
			else
				t=t->next=pb;
		}
		if(pb->h==NULL)     //挂物品链
			pb->h=pg;
		else{
			for(p=pb->h;p->next;p=p->next);
			p->next=pg;
		}
		pb->reminder-=g[i].v;
	}
	return h;
}


输出每个箱子中存储物品的编号

void PrintBox(BNode *h){
	BNode *pb;
	GNode *pg;
	for(pb=h;pb;pb=pb->next){
		for(pg=pb->h;pg;pg=pg->next)
			printf("%d\t",pg->gno);
		printf("\n");
	}
}

主函数

int main(void){
	int i,n;
	int v;
	Goods *g;
	BNode *h;
	int vv;
	scanf("%d%d",&n,&vv);
	g=(Goods*)malloc(sizeof(Goods)*n);
	for(i=0;i<n;i++){
		scanf("%d",&v);
		g[i].gno=i+1;
		g[i].v=v;
	}
	ShellSort(g,n);
	Print(g,n);
	printf("\n\n");
	h=CreateBox(g,n,vv);
	PrintBox(h);
	return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值