plgatc 发表于 2005-5-1 01:13

个人写的运输问题算法,还望指教

<P>/*************************************************************************
                         表上作业法解运输问题        

编程环境:VC++6.0     
程序说明:
Vogel法求初始解,位势法检验是否最优,递归搜索闭回路改进解。
*************************************************************************/
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;</P>
<P>#define MAX 100
#define M 999999</P>
<P>int status; //1唯一最优解,-1无穷多最优解</P>
<P>int num_a,num_b;
double a,b,temp_a,temp_b;
double u,v,pu,pv;
double ab,temp_ab;
double base;
int pbase;
struct element {
int r;
int c;
double value;
};
enum direction {mid,up,down,left,right};</P>
<P>void create();
void banner();
double dabs(double d);
void findinit();
void computeuv();
int check();
int  circle(enum direction dir,struct element cir[],int *t);
void improve();
void output();</P>
<P>void main() {
banner();
create();
printf("\n按回车确认后开始求解");
getchar();
getchar();
findinit();
improve();
switch(status) {
case 1:
  output();
  puts("\n原问题有唯一最优解。\n");
  puts("\n按回车结束");
  getchar();
  exit(0);
case -1:
  output();
  puts("\n原问题有无穷多最优解。\n");
  puts("\n按回车结束");
  getchar();
  exit(0);
}
}</P>
<P>void banner() {
printf("\t\t****************************************\n");
printf("\t\t         表上作业法解运输问题\n");
printf("\t\t                              Thunder\n");
printf("\t\t****************************************\n");
printf("\n");
}</P>
<P>void create() {
int i,j;
double sum_a,sum_b;
char confirm;
while(1) {
  printf("请输入产地个数:");
  scanf("%d",&amp;num_a);
  for(i=1;i&lt;=num_a;i++) {
   printf("A%d产量:",i);
   scanf("%lf",&amp;a);
  }
  for(i=1;i&lt;=num_a;i++) printf("A%d产量:%lg\t",i,a);
  printf("\n正确吗?:(y/n)");
  getchar();
  confirm=getchar();
  if (confirm=='y') break;
  else if(confirm=='n') continue;
}
while(1) {
  printf("\n请输入销地个数:");
  scanf("%d",&amp;num_b);
  for(i=1;i&lt;=num_b;i++) {
   printf("B%d销量:",i);
   scanf("%lf",&amp;b);
  }
  for(i=1;i&lt;=num_b;i++) printf("B%d销量:%lg\t",i,b);
  printf("\n正确吗?:(y/n)");
  getchar();
  confirm=getchar();
  if (confirm=='y') break;
  else if(confirm=='n') continue;
}
putchar('\n');
for(i=1;i&lt;=num_a;i++) {
  for(j=1;j&lt;=num_b;j++) {
   printf("A%d到B%d运价:",i,j);
   scanf("%lf",&amp;ab);
  }
  for(j=1;j&lt;=num_b;j++) printf("A%d到B%d:%lg\t",i,j,ab);
  printf("\n正确吗?:(y/n)");
  getchar();
  confirm=getchar();
  if(confirm=='n') i--;
  putchar('\n');
}
//处理产销不平衡的情况
sum_a=sum_b=0;
for(i=1;i&lt;=num_a;i++) sum_a+=a;
for(i=1;i&lt;=num_b;i++) sum_b+=b;</P>
<P> printf("总产量:%lg\t总销量:%lg",sum_a,sum_b);
if(sum_a==sum_b) printf("\t产销平衡。");
else if(sum_a&gt;sum_b) {
  printf("\t供大于求,增加假想销地B%d。\n",++num_b);
  b=sum_a-sum_b;
  for(i=1;i&lt;=num_a;i++) ab=0;
}
else if(sum_a&lt;sum_b){
  printf("\t供不应求,增加假想产地A%d。\n",++num_a);
  a=sum_b-sum_a;
  for(i=1;i&lt;=num_b;i++) ab=0;
}
//求解前的准备
for(i=1;i&lt;=num_a;i++)
  for(j=1;j&lt;=num_b;j++)
   base=pbase=0;
for(i=1;i&lt;=num_a;i++) temp_a=a;
for(i=1;i&lt;=num_b;i++) temp_b=b;
for(i=1;i&lt;=num_a;i++)
for(j=1;j&lt;=num_b;j++) temp_ab=ab;
//回显问题
printf("\n\n原问题为:\n\n");
   printf("产量:\n ");
for(i=1;i&lt;=num_a;i++) printf("A%d:%lg\t",i,a);
printf("\n运量:\n ");
for(i=1;i&lt;=num_b;i++) printf("B%d:%lg\t",i,b);
printf("\n运价为:\n");
for(i=1;i&lt;=num_a;i++) {
  putchar(' ');
  for(j=1;j&lt;=num_b;j++)
   printf("A%d-&gt;B%d:%lg\t",i,j,ab);
  putchar('\n');
}
}</P>
<P>double dabs(double d) {
if(d&gt;=0) return d;
else return -d;
}</P>
<P>void findinit() {
int i,j,k;
double r_penum,c_penum;
struct largest {
  char rc;
  int num;
  double value;
};
struct largest lar1,lar2;
int r=0,c=0;
double a1,a2,b1,b2,temp;</P>
<P> for(i=1;i&lt;=num_a;i++) {
  temp=temp_ab;
  for(j=1;j&lt;=num_b;j++)
   if(temp_ab&gt;temp) temp=temp_ab;
  a1=a2=temp;
  for(j=1;j&lt;=num_b;j++)
   if(temp_ab&lt;=a1) {
    a2=a1;
    a1=temp_ab;
   }
   else if(temp_ab&lt;=a2) a2=temp_ab;
  r_penum=dabs(a1-a2);
}</P>
<P> for(i=1;i&lt;=num_b;i++) {
  temp=temp_ab;
  for(j=1;j&lt;=num_a;j++)
   if(temp_ab&gt;temp) temp=temp_ab;
  b1=b2=temp;
  for(j=1;j&lt;=num_a;j++)  
   if(temp_ab&lt;=b1) {
    b2=b1;
    b1=temp_ab;
   }
   else if(temp_ab&lt;=b2) b2=temp_ab;
  c_penum=dabs(b1-b2);
}
/*
for(i=1;i&lt;=num_a;i++) printf("pa%d=%lg ",i,r_penum);
putchar('\n');
for(i=1;i&lt;=num_b;i++) printf("pb%d=%lg ",i,c_penum);
*/
temp=r_penum;
for(i=1;i&lt;=num_a;i++) if(r_penum&lt;temp) temp=r_penum;
for(i=1;i&lt;=num_b;i++) if(c_penum&lt;temp) temp=c_penum;</P>
<P> //考虑了有两个罚数相等的情况,大于两个相等只取其中两个进行比较
lar1.value=lar2.value=temp;
lar1.num=lar2.num=1;
lar1.rc=lar2.rc='r';
for(i=1;i&lt;=num_a;i++)
  if(r_penum&gt;=lar1.value) {
   lar2=lar1;
   lar1.rc='r';
   lar1.num=i;
   lar1.value=r_penum;
  }
  else if(r_penum&gt;=lar2.value) {
   lar2.rc='r';
   lar2.num=i;
   lar2.value=r_penum;
  }</P>
<P> for(i=1;i&lt;=num_b;i++)
  if(c_penum&gt;=lar1.value) {
   lar2=lar1;
   lar1.rc='c';
   lar1.num=i;
   lar1.value=c_penum;
  }
  else if(c_penum&gt;=lar2.value) {
   lar2.rc='c';
   lar2.num=i;
   lar2.value=c_penum;
  }</P>
<P> if(lar1.value==lar2.value&amp;&amp;(lar1.num!=lar2.num||lar1.rc!=lar2.rc)) {
  if(lar1.rc=='r'&amp;&amp;lar2.rc=='r') {
   temp=temp_ab;
   r=lar1.num;
      c=1;
   for(i=1;i&lt;=num_b;i++) {
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     r=lar1.num;
     c=i;
    }
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     r=lar2.num;
     c=i;
    }
   }
  }
  if(lar1.rc=='c'&amp;&amp;lar2.rc=='c') {
   temp=temp_ab;
   r=1;
      c=lar1.num;
   for(i=1;i&lt;=num_a-1;i++) {
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     c=lar1.num;
     r=i;
    }
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     c=lar2.num;
     r=i;
    }
   }
  }
  if(lar1.rc=='r'&amp;&amp;lar2.rc=='c') {
   temp=temp_ab;
   r=lar1.num;
      c=1;
   for(i=1;i&lt;=num_b;i++)
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     r=lar1.num;
     c=i;
    }
   for(i=1;i&lt;=num_a;i++)
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     c=lar2.num;
     r=i;
    }
  }
  if(lar1.rc=='c'&amp;&amp;lar2.rc=='r') {
   temp=temp_ab;
   r=1;
      c=lar1.num;
   for(i=1;i&lt;=num_b;i++)
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     r=lar2.num;
     c=i;
    }
   for(i=1;i&lt;=num_a;i++)
    if(temp_ab&lt;temp) {
     temp=temp_ab;
     c=lar1.num;
     r=i;
    }
  }
}
else {
  if(lar1.rc=='r') {
   r=lar1.num;
   c=1;
   temp=temp_ab;
   for(i=1;i&lt;=num_b;i++)
    if(temp_ab&lt;temp) {
     c=i;
     temp=temp_ab;
    }
  }
  else {
   r=1;
   c=lar1.num;
   temp=temp_ab;
   for(i=1;i&lt;=num_a;i++)
    if(temp_ab&lt;temp) {
     r=i;
     temp=temp_ab;
    }
  }
}
pbase=1;
if(temp_a&gt;temp_b) {
  base=temp_b;
  temp_a=temp_a-temp_b;
  temp_b=0;
  for(i=1;i&lt;=num_a;i++) temp_ab=M;
}
else if(temp_a&lt;temp_b) {
  base=temp_a;
  temp_b=temp_b-temp_a;
  temp_a=0;
  for(i=1;i&lt;=num_b;i++) temp_ab=M;
}
else if(temp_a==temp_b) {
  base=temp_a;
  temp_a=temp_b=0;
  for(i=1;i&lt;=num_a;i++) temp_ab=M;
  for(i=1;i&lt;=num_b;i++) temp_ab=M;
  k=0;
  for(i=1;i&lt;=num_a;i++) if(temp_a!=0) k=1;
  for(i=1;i&lt;=num_b;i++) if(temp_b!=0) k=1;
  if(k!=0) {
   k=0;
   for(i=1;i&lt;=num_a;i++) if(pbase!=1) {k=1;break;}
   for(j=1;j&lt;=num_b;j++) if(pbase!=1) {k=2;break;}
   if(k==1) pbase=1;
   else if(k==2) pbase=1;
  }
}
k=0;
for(i=1;i&lt;=num_a;i++) if(temp_a!=0) k=1;
for(i=1;i&lt;=num_b;i++) if(temp_b!=0) k=1;
if(k==0) return;
findinit();
}</P>
<P>void computeuv() {
int i,j,k;
for(i=1;i&lt;=num_a;i++)
  for(j=1;j&lt;=num_b;j++)
   if(pbase==1) {
    if(pu==1) {v=ab-u; pv=1;}
    if(pv==1) {u=ab-v; pu=1;}
   }
k=0;
for(i=1;i&lt;=num_a;i++) if(pu==0) k=1;
for(i=1;i&lt;=num_b;i++) if(pv==0) k=1;
if(k==1) computeuv();
}</P>
<P>int check() {
int i,j,k,l;
k=l=0;
for(i=1;i&lt;=num_a;i++)
  for(j=1;j&lt;=num_b;j++)
   if(pbase==0) {
    base=ab-u-v;
    if(base&lt;0) k=1;
    else if(base==0) l=1;
   }
/* for(i=1;i&lt;=num_a;i++){
  for(j=1;j&lt;=num_b;j++) printf("base %lg\t",base);
  putchar('\n');}
for(i=1;i&lt;=num_a;i++){
  for(j=1;j&lt;=num_b;j++) printf("pbase %d\t",pbase);
  putchar('\n');}
*/
if(k==0&amp;&amp;l==0) {status=1; return 1;}
else if(k==0&amp;&amp;l!=0) {status=-1; return 1;}
else return 0;
}</P>
<P>int circle(enum direction dir,struct element cir[],int *t) {
int i,j,k;
/*
putchar('\n');
for(i=1;i&lt;=*t;i++) printf("%d: r%d c%d\t",i, cir.r,cir.c);
putchar('\n');
*/
if((*t)!=1&amp;&amp;cir[(*t)].r==cir.r&amp;&amp;cir[*t].c==cir.c) {
  t--;
  return 1;
}
if(dir!=down) {
  k=0;
  for(i=cir[*t].r-1;i&gt;=1;i--)
   if(pbase.c]==1||(i==cir.r&amp;&amp;cir[*t].c==cir.c)) {k=1; break;}
  for(j=2;j&lt;=*t;j++) if(i==cir.r&amp;&amp;cir[*t].c==cir.c) k=0;
  if(k==1) {
   if(dir==up) cir[*t].value=0;
   else cir[*t].value=1;
   (*t)++;
   cir[*t].r=i;
   cir[*t].c=cir[(*t)-1].c;
   if(circle(up,cir,t)) return 1;
  }
}
if(dir!=up) {
  k=0;
  for(i=cir[*t].r+1;i&lt;=num_a;i++)
   if(pbase.c]==1||(i==cir.r&amp;&amp;cir[*t].c==cir.c)) {k=1; break;}
  for(j=2;j&lt;=*t;j++) if(i==cir.r&amp;&amp;cir[*t].c==cir.c) k=0;
  if(k==1) {
   if(dir==down) cir[*t].value=0;
   else cir[*t].value=1;
   (*t)++;
   cir[*t].r=i;
   cir[*t].c=cir[(*t)-1].c;
   if(circle(down,cir,t)) return 1;
  }
}
if(dir!=right) {
  k=0;
  for(i=cir[*t].c-1;i&gt;=1;i--)
   if(pbase.r]==1||(cir[*t].r==cir.r&amp;&amp;i==cir.c)) {k=1; break;}
  for(j=2;j&lt;=*t;j++) if(cir[*t].r==cir.r&amp;&amp;i==cir.c) k=0;
  if(k==1) {
   if(dir==left) cir[*t].value=0;
   else cir[*t].value=1;
   (*t)++;
   cir[*t].r=cir[(*t)-1].r;
   cir[*t].c=i;
   if(circle(left,cir,t)) return 1;
  }
}
if(dir!=left) {
  k=0;
  for(i=cir[*t].c+1;i&lt;=num_b;i++)
   if(pbase.r]==1||(cir[*t].r==cir.r&amp;&amp;i==cir.c)) {k=1; break;}
  for(j=2;j&lt;=*t;j++) if(cir[*t].r==cir.r&amp;&amp;i==cir.c) k=0;
  if(k==1) {
   if(dir==right) cir[*t].value=0;
   else cir[*t].value=1;
   (*t)++;
   cir[*t].r=cir[(*t)-1].r;
   cir[*t].c=i;
   if(circle(right,cir,t)) return 1;
  }
}
(*t)--;
return 0;
}</P>
<P>void improve() {
int i,j,k,t;
struct element base_in,base_out,cir;</P>
<P> for(i=1;i&lt;=num_a;i++) pu=0;
for(i=1;i&lt;=num_b;i++) pv=0;
u=0; pu=1;
computeuv();
if(check()) return;
for(i=1;i&lt;=num_a;i++)
  for(j=1;j&lt;=num_b;j++)
   if(pbase==0) break;
base_in.r=i;
base_in.c=j;
base_in.value=base;</P>
<P> for(i=1;i&lt;=num_a;i++)
  for(j=1;j&lt;=num_b;j++)
   if(pbase==0&amp;&amp;base&lt;base_in.value) {
    base_in.r=i;
    base_in.c=j;
    base_in.value=base;
   }</P>
<P> t=1;
cir.r=base_in.r;
cir.c=base_in.c;
cir.value=1;
if(!circle(mid,cir,&amp;t)) {
  printf("程序出错!按回车结束");
  getchar();
  exit(0);
}
t--;
// for(i=1;i&lt;=t;i++) printf("%d:r%d c%d v%lg\t",i,cir.r,cir.c,cir.value);
// putchar('\n');</P>
<P> for(i=2;i&lt;=t;i++) if(cir.value==1) break;
base_out=cir;
base_out.value=base.r].c];
k=1;
for(i=1;i&lt;=t;i++)
  if(k%2==0&amp;&amp;cir.value==1&amp;&amp;base.r].c]&lt;base_out.value) {
   base_out=cir;
   base_out.value=base.r].c];
   k++;
  }
  else if(cir.value==1) k++;
base.r].c]=0;
k=1;
for(i=1;i&lt;=t;i++) {
  if(k%2==1&amp;&amp;cir.value==1) {
   base.r].c]+=base_out.value;
   k++;
  }
  else if(k%2==0&amp;&amp;cir.value==1) {
   base.r].c]-=base_out.value;
   k++;
  }
}
pbase=0;
pbase=1;</P>
<P> improve();
}</P>
<P>void output() {
int i,j;
double sum=0;
printf("\n运量为:\n");
for(i=1;i&lt;=num_a;i++) {
  putchar(' ');
  for(j=1;j&lt;=num_b;j++)
   if(pbase==1) {
    printf("A%d-&gt;B%d:%lg\t",i,j,base);
    sum+=base*ab;
   }
   else printf("A%d-&gt;B%d:0\t",i,j);
  putchar('\n');
}
printf("\n最低总运费为:%lg\n",sum);
}
</P>

zhongguohelin 发表于 2010-3-4 22:40

good!   就是希望下次把格式稍稍注意下,这样可读性太差了呀~

enrique08 发表于 2010-3-31 22:56

太乱了吧!!!!!!!!!!:L

hzlhm 发表于 2010-4-4 08:01

乱了让人不想看了。。。。。。。。:funk:

liunengwu 发表于 2010-4-17 10:25

好!顶顶!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
页: [1]
查看完整版本: 个人写的运输问题算法,还望指教