表上作业法的源代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
表上作业法的源代码(总10页)
--本页仅作为文档封面,使用时请直接删除即可--
--内页可以根据需求调整合适字体及大小--
/* 表上作业法的源代码 */
#include ""
#include ""
#include ""
/* #define debug */
#define a(j) (*(C+(M-1)*N+j)) /*销量数组*/
#define b(i) (*(C+i*N+N-1)) /*产量数组*/
#define c(i,j) (*(C+i*N+j)) /*运价数组*/
#define x(i,j) (*(X+i*(N-1)+j)) /*运量数组 */
/*(<:基本解,>=:运量为0) */
#define s(i,j) (*(S+i*(N-1)+j)) /*检验数数组Sij */ #define u(i) (*(U+i)) /*位势数组Ui*/
#define v(i) (*(V+i)) /*位势数组Vi*/
#define cpi(k) ((CP+k)->i) /*闭回路点i标*/
#define cpj(k) ((CP+k)->j) /*闭回路点i标*/
#define cpf(k) ((CP+k)->f) /*闭回路点i标*/
/* f=0:j++; f=2:j--;
f=1;i--; f=3:i++; */
/*void TP(int M,int N,double *C,double *X); */
10 6 30
0 20 30 40 50 60
12 7 14 16 9 10 9 13 8 14
183 185 119 162 137 102 179 118 114
189 107 169 161 179 169 140 135 112
184 149 128 106 165 178 199 183 194
127 184 173 124 125 151 127 178 160
162 105 150 185 179 153 174 121 142
108 163 157 138 189 171 114 131 165
150 159 131 155 135 165 124 167 107
109 107 149 175 162 108 182 135 181
106 136 183 134 179 188 136 131 189
166 158 159 180 162 104 116 159 111
void main()
{
int M,N,i,j;
double *C; /*存储运价,产量及销量 */
double *X; /*存储运量分配方案 */
float z;
FILE *fp;
char fn[80];
double sum;
void TP(int M,int N,double *C,double *X);
printf("please input the data file name: ");
scanf("%s",fn);
{
printf("Cannot open the data file!");
getch();
exit(0);
}
fscanf(fp,"%d%d",&M,&N);
M++; N++;
X=(double *)malloc(sizeof(double)*(M-1)*(N-1));
C=(double *)malloc(sizeof(double)*M*N);
/* 把运价,供应量和需求量的数据读入到数组c(i,j); */
/*---高太光:这里可以直接定义固定的数组c(i,j),也可以从文件读取for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
fscanf(fp,"%f",&z);
c(i,j)=z;
}
printf("\n");
}
fclose(fp);
/* output c(i,j); */
printf("\n=============Data File================\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++)
{
printf("%",c(i,j));
}
printf("\n");
}
getch();
TP(M,N,C,X);
/* 输出产销分配方案; */
printf("\n=============Best Solution===================\n"); sum=0;
for(i=0;i<M-1;i++)
{
for(j=0;j<N-1;j++)
{
if(x(i,j)>=
printf("%10s","******");
else
{printf("%",x(i,j));
sum+=(x(i,j)*c(i,j));
}
printf("\n");
}
printf("\n\n\tThe min Cost is: %\n",sum);
getch();
free(X);
free(C);
}
struct PATH{
int i,j,f;
}; /*记录闭回路点结构*/
void TP(int M,int N, double *C,double *X)
{
double *U,*V,*S;
int MN1,m,n;
struct PATH *CP;
int k,i,j,l,k1,l1,ip;
double Cmin,sum;
int I0,J0,Imin,Jmin;
int fi,fj,fc,f;
MN1=(M-1)+(N-1)-1;
m=M-1;n=N-1;
S=(double *)malloc(sizeof(double)*(M-1)*(N-1));
U=(double *)malloc(sizeof(double)*M);
V=(double *)malloc(sizeof(double)*N);
CP=(struct PATH *)malloc(sizeof(struct PATH)*(MN1+1)); #ifdef debug
printf("\nM=%d,N=%d,m=%d,n=%d\n",M,N,m,n);
printf("\nb(i)is following:\n");
for(i=0;i<m;i++)
printf("%\t",b(i));
printf("\na(j)is folowing:\n");
for(j=0;j<n;j++)
printf("%\t",a(j));
printf("\n");
getch();
#endif
/*解初始化Xij=; */
for(i=0;i<m;i++)
for(j=0;j<n;j++)
x(i,j)=;
/*最小元素法求初始可行解 */
for(k=0;k<MN1;k++)
Cmin=;
for(i=0;i<m;i++)
{
fi=0;
for(l=0;l<k;l++)
{
/* 去除已经用过的行; */
if(i==cpi(l)){fi=1;break;}
}
if(fi==1)continue;
for(j=0;j<n;j++)
{
fj=0;
for(l=0;l<k;l++)
{
/* 去除已经用过的列; */
if(j==cpj(l)){fj=1;break;}
}
if(fj==1) continue;
if(Cmin>c(i,j))
{
Cmin=c(i,j);I0=i;J0=j;
#ifdef debug
printf("\n now c(i,j)=%\n",c(i,j));
#endif
}
} /*end for j */
}/* end for i */
/*得到了未划去的最小运价所在格的坐标(I0,J0)和最小运价Cmin */ if(k>0)
{if(Cmin==&&cpi(k-1)==0)
{for(l1=0;l1<m;l1++)
if(x(l1,cpj(k-1))==
{x(l1,cpj(k-1))=0;
}
}
else if(Cmin==&&cpi(k-1)!=0)
{for(l1=0;l1<n;l1++)
if(x(cpi(k-1),l1)==
{x(cpi(k-1),l1)=0;
}
}
}
if(b(I0)<a(J0))
{
cpi(k)=I0;cpj(k)=-1;
x(I0,J0)=b(I0);
printf("I0=%d,J0=%d,x(I0,J0)=%,k=%d,cpi(k)=%d,cpj(k)=%d\n",I0,J0,x(I0,J0),k,cpi(k),cpj(k)); #endif
a(J0)-=b(I0);
b(I0)=0;
}
else
{
cpi(k)=-1;cpj(k)=J0;
x(I0,J0)=a(J0);
#ifdef debug
printf("I0=%d,J0=%d,x(I0,J0)=%,k=%d,cpi(k)=%d,cpj(k)=%d\n",I0,J0,x(I0,J0),k,cpi(k),cpj(k)); #endif
b(I0)-=a(J0);
a(J0)=0;
}
} /*END FOR K 用最小元素法求得了初使可行解*/
/*输出初始可行解*/
printf("\n=============init Solution===================\n");
sum=0;
for(i=0;i<M-1;i++)
{
for(j=0;j<N-1;j++)
{
if(x(i,j)>=
printf("%10s","******");
else
{printf("%",x(i,j));
sum+=(x(i,j)*c(i,j));
}
}
printf("\n");
}
printf("\n\n\tThe Cost is: %\n",sum);
getch();
/***************循环换入换出,直到检验数为非负数*****************************/ /*循环决定换入变量 */
while(1)
{
/*位势置初值Ui,Vi= */
for(i=0;i<m;i++)
u(i)=;
for(j=0;j<n;j++)
v(j)=;
/*求位势*/
l=0;u(0)=0;
for(i=0;i<m;i++)
{
if(u(i)>=&&v(j)>=&&x(i,j)<
{
cpi(l)=i;cpj(l)=j;l++; /*记录未求过位势的位置*/
}
else if(x(i,j)<&&u(i)<
{v(j)=c(i,j)-u(i);}
else if(x(i,j)<&&v(j)<
{u(i)=c(i,j)-v(j);}
}/*end for j */
}/*end for i */
/*按记录位置求其余位势*/
if(l>0)
{
while(1)
{
ip=0;
for(k=0;k<l;k++)
{
i=cpi(k);j=cpj(k);
if((u(i)>=&&(v(j)>=&&(x(i,j)<)
{
cpi(ip)=i;cpj(ip)=j;ip++; /*记录未求过位势的位置*/ }
else if(x(i,j)<&&u(i)<
{v(j)=c(i,j)-u(i);}
else if(x(i,j)<&&v(j)<
{u(i)=c(i,j)-v(j);}
}/*end for k */
if(ip==0)break;
l=ip;
}/*end for while */
} /*end if l */
#ifdef debug
printf("\nU(i):");
for(i=0;i<m;i++)
{printf("%",u(i));
}
printf("\nV(j):");
for(j=0;j<n;j++)
{printf("%",v(j));
}
printf("\n");
#endif
/*求检验数*/
for(j=0;j<n;j++)
{ s(i,j)=;
if(x(i,j)>= s(i,j)=c(i,j)-u(i)-v(j);
}
}
/*求最小检验数*/
Cmin=;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(Cmin>s(i,j))
{Cmin=s(i,j);I0=i;J0=j;}
}
}
#ifdef debug
printf("\ncheck number:\n");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("s(%d,%d)=%\n",i,j,s(i,j));
}
printf("\n");
}
printf("Smin=%",Cmin);
getch();
#endif
if(Cmin>=0) return; /*已经得到最优解,返回主程序*/ /*此时找到了入基变量X(I0,J0) */
/*求闭回路*/
for(k=0;k<MN1;k++)
{
cpf(k)=-1;
}/*end for k */
cpi(0)=I0;cpj(0)=J0;
k=0;
while(1)
{
f=cpf(k);
/*设置闭回路搜索方向*/
while(1)
{
i=cpi(k);j=cpj(k);
fc=0;
f++;
if(f>=4)break;
/*避免反向搜索*/
if(k>0)
{
if(f==0&&cpf(k-1)==2) continue;
else if(f==1&&cpf(k-1)==3)continue; else if(f==2&&cpf(k-1)==0)continue; else if(f==3&&cpf(k-1)==1)continue; }
if(f==0)
{/*沿J+方向搜索*/
while(1)
{
j++;
if(j>=n){fc=2;break;}
if((i==I0)&&(j==J0))
{fc=1;break;}
if(s(i,j)>=
{fc=3;break;}
}
}/*end j+ */
else if(f==1)
{ /*沿i-方向搜索*/
while(1)
{ i--;
if(i<0){fc=2;break;}
if((i==I0)&&(j==J0)){fc=1;break;} if(s(i,j)>={fc=3;break;}
}
}/*end if=1 */
else if(f==2)
{/*沿J-方向搜索*/
while(1)
{
j--;
if(j<0){fc=2;break;}
if((i==I0)&&(j==J0)){fc=1;break;} if(s(i,j)>={fc=3;break;}
}
} /*end f==2 */
else if(f==3)
{/*沿I+方向搜索*/
while(1)
{
i++;
if(i>=m){fc=2;break;}
if((i==I0)&&(j==J0)){fc=1;break;}
}
}/*end f==3 */
if((fc==1)||(fc==3))break;
}/*end while flag 2 */
if(fc==0)
{/*沿些方向搜索失败,退回回到前一点*/
k--;
}
else if(fc==1)break; /*搜索完成*/
else if(fc==3)
{/*沿此方向搜索成功,前进一点*/
k++;
cpi(k)=i;cpj(k)=j;
#ifdef debug
printf("\n");
printf("k=%d,cpi(k)=%d,cpj(k)=%d,cpf(k)=%d,x(i,j)=%\n",k,cpi(k),cpj(k),cpf(k),x(cpi(k),cpj(k))); getch();
#endif
cpf(k)=-1;
}
}/*end while */
/*去除闭回路中的非转折点*/
l=0;
while(l<k-1)
{ i=l+1;
while(i<=k)
{if(cpf(l)==cpf(i)) i++;
else break;
}
if(i>(l+1))
{j=l+1;
k1=k-(i-j);
/*如果某些点前进方向相同,则去除中间各点*/
while(i<=k)
{cpi(j)=cpi(i);
cpj(j)=cpj(i);
cpf(j)=cpf(i);
i++;j++;
}
l+=2;
k=k1;
}
else l++;
}/*end while l<k-1 */
/*查找闭回路上基本解的最小值*/
Cmin=x(cpi(1),cpj(1));
Imin=cpi(1);Jmin=cpj(1);
{if(Cmin>x(cpi(i),cpj(i)))
{Cmin=x(cpi(i),cpj(i));
Imin=cpi(i);Jmin=cpj(i);
}
}
/*换入基变量*/
x(I0,J0)=Cmin;
for(i=1;i<=k;i+=2)
{x(cpi(i),cpj(i))-=Cmin;
if((i+1)<=k) x(cpi(i+1),cpj(i+1))+=Cmin;
}
x(Imin,Jmin)=;
}
free(CP);
free(V);
free(U);
free(S);
QUIT: return;
}
================END====================
11。