实现一个物流配送系统的货物分配以及运输路线的数据结构实验。从一个始发站向周围用卡车运送货物,是运送路线尽量达到最优,运送的成本(卡车数量尽量少)尽量达到最小,利用计算机完成相应计算并给出相应的送货方案。将路径问题看成一个旅行商问题,用贪心策略先求出路径,然后继续用贪心策略装货物并用车配送。
#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
时间: 2024-10-13 11:21:00