实现一个物流配送系统的货物分配以及运输路线的数据结构实验。从一个始发站向周围用卡车运送货物,是运送路线尽量达到最优,运送的成本(卡车数量尽量少)尽量达到最小,利用计算机完成相应计算并给出相应的送货方案。将路径问题看成一个旅行商问题,用贪心策略先求出路径,然后继续用贪心策略装货物并用车配送。
#include <iostream>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int oo=1e9;
vector<int>tu[100];
vector<int>ww[100];
int tnum;///物品种类数目
struct thing
{
char name[30];
int l,w,h;
void set(char p[],int ll,int ww,int hh)
{
strcpy(name,p);
l=ll;
w=ww;
h=hh;
}
} wp[100]; ///物品
struct hhh
{
char name[30];
int n;
void set(char x[],int nn)
{
strcpy(name,x);
n=nn;
}
};///所需物品名称及数量
struct xixi
{
int num;
hhh a[100];
xixi()
{
num=0;
}
} xq[100]; ///各地需求的物品数目
int dd[100][100];///任意两点距离
char name[100][30];///起点名字,各地名字
struct hh
{
char name[30];
int n;///数目
int des;///目的地
void set(char x[],int nn,int dest)
{
strcpy(name,x);
n=nn;
des=dest;
}
};
void floyd(int n)
{
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dd[i][j]=min(dd[i][k]+dd[k][j],dd[i][j]);
}
void spfa(int s,int e,int n,int flag)///最短路记录路径
{
int dist1[100];
int pre[100]; ///前驱
memset(pre,-1,sizeof(pre));
queue<int>q;
for(int i=0; i<=n; i++)
dist1[i]=oo;
bool vis[100]= {0};
q.push(e);
dist1[e]=0;
while(!q.empty())
{
int h=q.front();
q.pop();
vis[h]=0;
for(int i=0,l=tu[h].size(); i<l; i++)
{
int v=tu[h][i];
int w=ww[h][i];
if (dist1[v]>dist1[h]+w)
{
pre[v]=h;
dist1[v]=dist1[h]+w;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
int x=s;
cout<<name[x];
while(pre[x]!=-1)
{
x=pre[x];
cout<<"--->"<<name[x];
}
if(flag)
cout<<"回家"<<endl<<endl;
else cout<<"卸";
}
void ssort(int &a,int &b,int &c)
{
if(a>b)
swap(a,b);
if(b>c)
swap(b,c);
if(a>b)
swap(a,b);
}
int findd(char x[])
{
for(int i=1; i<=tnum; i++)
if(!strcmp(x,wp[i].name))
return i;
return 0;
}
void solve(int n)
{
int num=1;
for(int i=1; i<=n; i++)
{
for(int j=0; j<xq[i].num; j++)
{
int tt=findd(xq[i].a[j].name);
//cout<<i<<' '<<xq[i].a[j].name<<endl;
int a1=wp[tt].h,a2=wp[tt].w,a3=wp[tt].l;
int b1=wp[0].h,b2=wp[0].w,b3=wp[0].l;
int x=(b1/a1)*(b2/a2)*(b3/a3),tem=0;
//cout<<xq[i].a[j].name<<" tt="<<tt<<endl;
//cout<<"a1="<<a1<<" a2="<<a2<<" a3="<<a3<<endl;
//cout<<"b1="<<b1<<" b2="<<b2<<" b3="<<b3<<endl;
if(x)
tem=xq[i].a[j].n/x;
while(tem--)
{
cout<<"车"<<num++<<" 装"<<x<<"个去"<<name[i]<<"的"<<xq[i].a[j].name<<endl;
cout<<"路径为:"<<endl;
spfa(0,i,n,0);cout<<xq[i].a[j].name<<" ";
spfa(i,0,n,1);
}
if(x)
xq[i].a[j].n%=x;
}
}
floyd(n);
bool vis[100]= {0};
int nn=n;
for(int i=1; i<=n; i++)
{
int flag=1;
for(int j=0; j<xq[i].num; j++)
if(xq[i].a[j].n)
{
flag=0;
break;
}
if(flag)
vis[i]=1,nn--;
}
int now=0,s=0;
vector<int>tx;
while(s++<nn)
{
int min0=oo,k=0;
for(int i=1; i<=n; i++)
if(!vis[i])
{
if(min0>dd[now][i])
min0=dd[now][i],k=i;
}
//cout<<now<<' '<<k<<endl;
tx.push_back(k);
vis[k]=1;
now=k;
}
int l=tx.size(),i=0,bj=0,v=wp[0].h*wp[0].l*wp[0].w,sum[1000]= {0}; ///sum[i][0]记录车i总共装的货物,sum[i][j]记录车装的第j种货物的数量
//for(int i=0;i<l;i++)
//cout<<tx[i]<<' '<<endl;cout<<endl;
vector<hh>che[1000];
//cout<<"l="<<l<<endl;
//int xxx=0;&&xxx++<=10
//cout<<v<<endl<<endl;
while(i<l)
{
//cout<<i<<"="<<tx[i]<<":"<<bj<<endl;
int j=0;
while(j<xq[tx[i]].num)
{
//cout<<j<<endl;
if(xq[tx[i]].a[j].n<=0)
{
j++;
continue;
}
int f=findd(xq[tx[i]].a[j].name),tv=wp[f].h*wp[f].l*wp[f].w;
//cout<<tv<<endl;
int t0=v-sum[bj],t1=t0/tv;
if(t1>=1)
{
int min0=min(t1,xq[tx[i]].a[j].n);
sum[bj]+=tv*min0;
hh tt;
tt.set(xq[tx[i]].a[j].name,min0,tx[i]);
//cout<<xq[tx[i]].a[j].name<<' '<<t1<<":"<<xq[tx[i]].a[j].n<<' '<<tx[i]<<endl;
che[bj].push_back(tt);
if(xq[tx[i]].a[j].n<=t1)
j++;
else
xq[tx[i]].a[j].n-=min0;
// cout<<xq[tx[i]].a[j].name<<' '<<t1<<":"<<xq[tx[i]].a[j].n<<' '<<tx[i]<<endl<<endl;;
}
else
bj++;
}
i++;
}
//cout<<bj<<endl;
for(int i=0; i<=bj; i++)
{
//cout<<sum[i][0]<<":"<<endl;
int l=che[i].size();
/*for(int j=0; j<l; j++)
cout<<che[i][j]<<' ';
cout<<endl;
for(int j=1; j<=l; j++)
cout<<sum[i][j]<<' ';
cout<<endl;
*/
if(!l)break;
cout<<"车"<<num++<<" 装";
for(int j=0; j<l; j++)
cout<<che[i][j].n<<"个去"<<name[che[i][j].des]<<"的"<<che[i][j].name<<" ";
cout<<endl<<"路径为:"<<endl;
for(int j=0; j<l; j++)
{
if(j==0)
spfa(0,che[i][j].des,n,0),cout<<che[i][j].name<<" ";
else
spfa(che[i][j-1].des,che[i][j].des,n,0),cout<<che[i][j].name<<" ";
}
spfa(che[i][l-1].des,0,n,1);
}
}
bool cmp(thing a,thing b)
{
return a.l*a.h*a.w<b.l*b.h*b.w;
}
int main()
{
int n;
cout<<"请输入目的地的数量"<<endl;
cin>>n;
cout<<"请输入起点名称"<<endl;
cin>>name[0];///起点名称
cout<<"请输入"<<n<<"个目的地的名称"<<endl;
for(int i=1; i<=n; i++)
cin>>name[i];///各点名称
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
dd[i][j]=i==j?0:oo;
cout<<"请输入两地之间的路径(输入两相同地点结束输入):"<<endl<<"示例输入:"<<name[0]<<' '<<name[1]<<" 12表示"<<name[0]<<"与"<<name[1]<<"距离为12"<<endl;
while(1)
{
char t1[100],t2[100];
int dis,tt1=0,tt2=0;
cin>>t1>>t2>>dis;///各点之间距离
if(!strcmp(t1,t2))break;
if(strcmp(t1,name[0]))
for(int i=1; i<=n; i++)
if(!strcmp(name[i],t1))
{
tt1=i;
break;
}
if(strcmp(t2,name[0]))
for(int i=1; i<=n; i++)
if(!strcmp(name[i],t2))
{
tt2=i;
break;
}
tu[tt1].push_back(tt2);
tu[tt2].push_back(tt1);
ww[tt1].push_back(dis);
ww[tt2].push_back(dis);
dd[tt1][tt2]=dd[tt2][tt1]=dis;
}
cout<<"请输入所有需求的物品名称及对应的长宽高:(输入0 0 0 0结束输入)"<<endl;
tnum=0;///物品种类数目
while(1)
{
char tem[30];
int l,w,h;
cin>>tem>>l>>w>>h;
if(!strcmp(tem,"0")&&!l&&!w&&!h)
break;
ssort(h,w,l);
wp[++tnum].set(tem,l,w,h);
}
sort(wp+1,wp+tnum+1,cmp);
for(int i=1; i<=n; i++)
{
cout<<"请输入"<<name[i]<<"需求的种类数目:"<<endl;
cin>>xq[i].num;
for(int j=0; j<xq[i].num; j++)
{
cout<<"请输入第"<<j+1<<"种物品的名称以及需求量(示例:pig 15)"<<endl;
char tem[30];
cin>>tem;
int nnn;
cin>>nnn;
xq[i].a[j].set(tem,nnn);
}
cout<<endl;
}
int l,h,w;
cout<<"请输入卡车的长,宽,高:"<<endl;
cin>>l>>h>>w;///卡车容量
ssort(h,w,l);
char tem[30]= {"car"};
wp[0].set(tem,l,w,h);
cout<<endl;
solve(n);
return 0;
}
测试数据:
7
0
1
2
3
4
5
6
7
0 1 2
0 6 7
1 4 3
2 5 8
1 2 2
2 3 1
3 4 1
5 4 4
5 6 5
6 7 1
1 7 3
0 0 0
cup 1 4 6
cat 4 7 2
bag 7 3 1
flag 6 3 1
dog 4 4 2
pig 5 8 9
0 0 0 0
3
cup 4
dog 9
pig 10
2
dog 5
flag 3
3
bag 3
cup 2
flag 1
1
dog 1
2
cat 4
bag 2
1
pig 1
1
flag 1
3 9 18