表上作业法的函数

14 篇文章 0 订阅
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**只用修改这里***********************************/
#define M 6
#define N 8
double tariff[M][N]={//运费
6, 2, 6, 7, 4, 2, 5, 9,
4, 9, 5, 3, 8, 5, 8, 2,
5, 2, 1, 9, 7, 4, 3, 3,
7, 6, 7, 3, 9, 2, 7, 1,
2, 3, 9, 5, 7, 2, 6, 5,
5, 5, 2, 2, 8, 1, 4, 3
};
double product[M]={60,55,51,43,41,52};//产量
double need[N]={35,37,22,32,41,32,43,38};//需求
/***********************************只用修改这里**/

struct ssp{
	double p;
	int m,n;
};

int compar(const void *a,const void *b){
	struct ssp *aa,*bb;
	aa=(struct ssp*)a;
	bb=(struct ssp*)b;
	if((aa->p)>(bb->p)) return 1;
	if((aa->p)==(bb->p)) return 0;
	return -1;
}

void find_loop(int pmc,int pnc,char* map,int m,int n,struct ssp* pssp,int* k);

void fun(double *tar,double *pro,int m,double *nee,int n){
	struct ssp* pssp;
	double *t,*pm,*pn;
	int i,j,k;
	double a,b,c;
	char *map,*mpm,*mpn;
	int pmc,pnc;

	pssp=(struct ssp*)malloc(sizeof(struct ssp)*m*n);
	t=(double*)malloc(sizeof(double)*m*n);
	pm=(double*)malloc(sizeof(double)*m);
	pn=(double*)malloc(sizeof(double)*n);
	map=(char*)malloc(sizeof(char)*m*n);
	mpm=(char*)malloc(sizeof(char)*m);
	mpn=(char*)malloc(sizeof(char)*n);

	memset(t,0,sizeof(double)*m*n);
	memcpy(pm,pro,sizeof(double)*m);
	memcpy(pn,nee,sizeof(double)*n);

	/*基本可行解*/
	k=0;
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			pssp[k].p=*(tar+i*n+j);
			pssp[k].m=i;pssp[k].n=j;
			k++;
		}
	}
	qsort(pssp,m*n,sizeof(struct ssp),compar);
	for(k=0;k<m*n;k++){
		a=pm[pssp[k].m];
		b=pn[pssp[k].n];
		if(a<b){
			*(t+pssp[k].m*n+pssp[k].n)=a;
			pm[pssp[k].m]=0;pn[pssp[k].n]-=a;
		}else{
			*(t+pssp[k].m*n+pssp[k].n)=b;
			pn[pssp[k].n]=0;pm[pssp[k].m]-=b;
		}
	}

	/*寻找最优解*/
	while(1){
		memset(map,0,sizeof(char)*m*n);
		memset(pm,0,sizeof(double)*m);
		memset(pn,0,sizeof(double)*n);
		memset(mpm,0,sizeof(char)*m);
		memset(mpn,0,sizeof(char)*n);

		/*判断方案是否最优*/
		k=0;
		for(i=0;i<m;i++){
			for(j=0;j<n;j++){
				if(*(t+i*n+j)!=0){
					*(map+i*n+j)=1;
				}else{
					pssp[k].p=*(tar+i*n+j);
					pssp[k].m=i;pssp[k].n=j;
					k++;
				}
			}
		}
		mpm[0]=1;
		pmc=1;pnc=0;
		while(pnc!=n||pmc!=m){
			for(i=0;i<m;i++){
				if(mpm[i]==0) continue;
				for(j=0;j<n;j++){
					if(*(map+i*n+j)==0) continue;
					if(mpn[j]==1) continue;
					pn[j]=*(tar+i*n+j)-pm[i];
					mpn[j]=1;pnc++;
				}
			}
			for(i=0;i<n;i++){
				if(mpn[i]==0) continue;
				for(j=0;j<m;j++){
					if(*(map+j*n+i)==0) continue;
					if(mpm[j]==1) continue;
					pm[j]=*(tar+j*n+i)-pn[i];
					mpm[j]=1;pmc++;
				}
			}
		}
		b=0;j=-1;
		for(i=0;i<k;i++){
			a=pssp[i].p-pm[pssp[i].m]-pn[pssp[i].n];
			if(a<0&&(b==0||a<b)){
				b=a;j=i;
			}
		}
		if(j==-1) break;
		pmc=pssp[j].m;//记录入基空格坐标
		pnc=pssp[j].n;//记录入基空格坐标

		/*下一个基本可行解*/
		find_loop(pmc,pnc,map,m,n,pssp,&k);
		b=0;
		for(i=0;i<k;i++){
			if(pssp[i].p<0){
				a=*(t+pssp[i].m*n+pssp[i].n);
				if(b==0||a<b) b=a;
			}
		}
		for(i=0;i<k;i++){
			if(pssp[i].p<0){
				*(t+pssp[i].m*n+pssp[i].n)-=b;
			}else{
				*(t+pssp[i].m*n+pssp[i].n)+=b;
			}
		}
	}
	
	/*打印最优解*/
	c=0;
	printf("【 solution 】\n\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(*(t+i*n+j)==0) printf("%8s","------");
			else printf("%8.3f",*(t+i*n+j));
			c+=(*(t+i*n+j))*(*(tar+i*n+j));
		}
		printf("\n");
	}
	printf("\ncost: %-8.3f\n\n",c);

	free(t);free(pm);free(pn);free(pssp);free(map);free(mpm);free(mpn);
}

void find_loop(int pmc,int pnc,char* map,int m,int n,struct ssp* pssp,int* k){
	int i,d,c;
	int x,y;
	x=pmc;y=pnc;
	*(map+x*n+y)=3;
	d=1;c=0;
	pssp[c].m=x;pssp[c].n=y;pssp[c].p=1;
	while(d!=0){
		if(d==1){
			for(i=0;i<n;i++){
				if(c!=0&&*(map+x*n+i)==3){
					d=0;break;
				}
				if(*(map+x*n+i)==1){
					*(map+x*n+i)=2;
					c++;
					d=2;y=i;
					pssp[c].m=x;pssp[c].n=y;
					if(c%2==0) pssp[c].p=1;
					else pssp[c].p=-1;
					break;
				}
			}
			if(i==n){
				*(map+x*n+y)=0;
				d=2;c--;
				x=pssp[c].m;
			}
		}else{
			for(i=0;i<m;i++){
				if(c!=0&&*(map+i*n+y)==3){
					d=0;break;
				}
				if(*(map+i*n+y)==1){
					*(map+i*n+y)=2;
					c++;
					d=1;x=i;
					pssp[c].m=x;pssp[c].n=y;
					if(c%2==0) pssp[c].p=1;
					else pssp[c].p=-1;
					break;
				}
			}
			if(i==m){
				*(map+x*n+y)=0;
				d=1;c--;
				y=pssp[c].n;
			}
		}
	}
	*k=c+1;
}

int main(){
	fun(&tariff[0][0],product,M,need,N);
	return 0;
}
【 solution 】


  ------  19.000  ------  ------  41.000  ------  ------  ------
   1.000  ------  ------  32.000  ------  ------  ------  ------
  ------  11.000  ------  ------  ------  ------  40.000  ------
  ------  ------  ------  ------  ------   5.000  ------  38.000
  34.000   7.000  ------  ------  ------  ------  ------  ------
  ------  ------  22.000  ------  ------  27.000   3.000  ------


cost: 664.000


Press any key to continue

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值