这是2020中兴捧月算法大赛迪杰斯特拉赛道初赛的个人代码,所述程序在初赛中获得了84分,虽然没有进入决赛圈,但是作为第一次参加比赛,能获得区域优胜奖已经很开心了,以下便是本次参赛代码,思路:货物打包+迪杰斯特拉+动态权值,代码较长,谨慎服用

   1 #include <iostream>
   2 #include <stdlib.h>
   3 #include<sstream>
   4 #include<vector>
   5 #include<stdint.h>
   6 #include<string>
   7 #include <iomanip>
   8 
   9 constexpr auto maxnum = 5000;        //最大站点数
  10 constexpr auto INF = 10000;          //路径权值,代表不通
  11 
  12 using namespace std;
  13 
  14 string outroad[maxnum][200];                       //存放成功运输的货物的路径,第1列表示货物名称
  15 int success[maxnum][100];                         //成功运输的货物,第1列表示运送轨道个数,第2列以后表示运送的列车号
  16 static double carweight;          //每节车的承重
  17 static int carnum;                //每条轨道的列车数
  18 static int goodsnum;              //货物总数
  19 static int losenum = 0;           //未成功规划的货物数量
  20 static double loseweight = 0;     //未成功规划的货物重量
  21 static int s = 1;
  22 
  23 /**首先定义一个站点结构**/
  24 struct Node {
  25     string index;                 //站点下标
  26     string rname;                 //通往该站的轨道名称
  27     Node* next;                   //指向下一站点的指针
  28     int weight = 1;
  29     int handlers[100] = { 0 };      //表示该站点到下一站点的轨道上对应车厢的分拣员数
  30     int delcar[15][2];              //记录该站点到哪些站点的某个车厢需要拣货员,[2][0]=a,[2][1]=50,代表通往a站台的50号工位
  31 };
  32 
  33 /**定义一条轨道的结构**/
  34 struct Edge {
  35     string m, v;                    //轨道连接的两个站点
  36     string railname;                //轨道名称
  37     double car[100] = { 0 };        //存放到达该轨道的每节列车运货情况(t),0表示未占用
  38     string gname[100] = { "null" }; //存放该节车厢上最早存放的货物的名称
  39 };
  40 
  41 /*货物*/
  42 struct Goods
  43 {
  44     int wcar;                       //该货物运输的车厢
  45     int nows;                        //该货物是当前第nows个成功的货物
  46     int whichcar;                    //装在该车箱
  47     string name;                     //货物名称
  48     double goodweight;              //货物重量
  49     string startstation;            //起点
  50     string endstation;              //目标点
  51     vector<string> midstation;      //必经结点
  52     int roadnum;                    //该货物运输经过了多少路轨
  53     double allweight;               //一类货物(起点终点相同)打包在一起的总重量
  54     int listnum[100] = { 0 };    //初始化一个数组,记录第几个轨道用的是哪个车厢
  55 };
  56 
  57 /**定义地图**/
  58 struct Graph {
  59     int nodenum;                            //站点数
  60     int edgenum;                           //轨道数
  61     string name[maxnum];            //存放站点名称的数组(假设站点上限不超过500)
  62     string edgename[1000];         //存放轨道名称的数组(假设站点上限不超过500)
  63     int worker[maxnum];             //存放各站点的搬运人数(假设站点上限不超过500)
  64     Node* headnode[maxnum];         //定义一个数组存放头节点
  65     Edge* edgeuse[maxnum];            //存放路轨使用情况
  66     Goods* out[maxnum];             //存放成功运输的货物
  67 };
  68 
  69 /*定义路径结点*/
  70 struct route
  71 {
  72     string process;               //经过站点名称
  73     string trail;                 //到达该站点的轨道名称
  74     route* next;                  //指向下一站点的指针
  75 
  76 };
  77 
  78 /**初始化一个只含有顶点的图**/
  79 Graph* initgraph(int n) {
  80     Graph* mygraph = new Graph;
  81     mygraph->nodenum = n;
  82     mygraph->edgenum = 0;
  83     string line, word;
  84     vector<string>row;
  85     for (int i = 1; i <= n; i++) {
  86         mygraph->headnode[i] = nullptr;       //头指针的next为空
  87 
  88         getline(cin, line);
  89         row.clear();
  90         stringstream s(line);
  91         while (getline(s, word, \',\'))
  92         {
  93             row.push_back(word);
  94         }
  95         mygraph->name[i] = row[0];
  96         mygraph->worker[i] = atoi(row[1].c_str());
  97     }
  98     return mygraph;     //返回的是一个只含有头指针的数组
  99 }
 100 
 101 /**将站点名字与数组下标进行转换**/
 102 int change(Graph* mygraph, string mbname)
 103 {
 104     for (int i = 1; i <= mygraph->nodenum; i++) {
 105         if (mygraph->name[i] == mbname) {
 106             return i;
 107         }
 108     }
 109 }
 110 
 111 /**将轨道名字与数组下标进行转换**/
 112 int echange(Graph* mygraph, string ename)
 113 {
 114     for (int i = 1; i <= mygraph->edgenum; i++) {
 115         if (mygraph->edgename[i] == ename) {
 116             return i;
 117         }
 118     }
 119 }
 120 
 121 /**将图链表往后延续,插入边**/
 122 void insertedge(Graph* mygraph, Edge* myedge) {
 123     mygraph->edgename[s++] = myedge->railname;                  //将轨道名字存进去
 124     Node* node = new Node;
 125     node->index = myedge->v;                                    //因为是从v指向m,所以要找到一个下标是n的节点,使其在第m个节点后
 126     int M = change(mygraph, myedge->m);
 127     node->rname = myedge->railname;
 128     node->next = mygraph->headnode[M];
 129     mygraph->headnode[M] = node;                                //此处相当于是前插法创建链表
 130 
 131     /**因为是无向图还需反过来插一次**/
 132     Node* node1 = new Node;
 133     node1->index = myedge->m;                                   //因为是从v指向m,所以要找到一个下标是n的节点,使其在第m个节点后
 134     int V = change(mygraph, myedge->v);
 135     node1->rname = myedge->railname;
 136     node1->next = mygraph->headnode[V];
 137     mygraph->headnode[V] = node1;
 138 }
 139 
 140 /**开始建图**/
 141 Graph* buildgraph() {
 142     Graph* mygraph = new Graph;
 143     Edge* myedge = new Edge;
 144     int nodnum, edgnum;
 145 
 146     string line, word;
 147     vector<string> row;
 148     getline(cin, line);                             //流读入
 149     row.clear();
 150     stringstream s(line);
 151     while (getline(s, word, \',\'))
 152     {
 153         row.push_back(word);
 154     }
 155     nodnum = atoi(row[0].c_str());                  //将string型转为int
 156     edgnum = atoi(row[1].c_str());
 157     carnum = atoi(row[2].c_str());
 158     carweight = atof(row[3].c_str());
 159 
 160     mygraph = initgraph(nodnum);
 161     mygraph->edgenum = edgnum;
 162 
 163     for (int i = 1; i <= edgnum; i++) {
 164         Edge* E = new Edge;
 165         getline(cin, line);
 166         row.clear();
 167         stringstream s(line);
 168         while (getline(s, word, \',\'))
 169         {
 170             row.push_back(word);
 171         }
 172         E->railname = row[0];
 173         E->m = row[1];
 174         E->v = row[2];
 175         mygraph->edgeuse[i] = E;                        //将轨道放入
 176         insertedge(mygraph, E);
 177     }
 178     return mygraph;
 179 }
 180 
 181 /*读取货物信息*/
 182 void inishgood(Graph* mygraph)
 183 {
 184     string line, word;
 185     vector<string> row;
 186     getline(cin, line);
 187     row.clear();
 188     stringstream s(line);
 189     while (getline(s, word, \',\'))
 190     {
 191         row.push_back(word);
 192     }
 193     goodsnum = stoi(row[0].c_str());                      //货物总数
 194 
 195     for (int i = 1; i <= goodsnum; i++) {
 196         getline(cin, line);
 197         row.clear();
 198         stringstream s(line);
 199         while (getline(s, word, \',\'))
 200         {
 201             row.push_back(word);
 202         }
 203         Goods* good = new Goods;
 204         good->name = row[0];
 205         good->startstation = row[1];
 206         good->endstation = row[2];
 207         good->goodweight = atof(row[3].c_str());
 208         good->midstation.clear();
 209         for (int j = 4; j < row.size(); j++) {
 210             good->midstation.push_back(row[j]);
 211         }
 212         mygraph->out[i] = good;                                //将该货物信息放入地图
 213         loseweight = loseweight + good->goodweight;            //假设所有货物最开始都未运输成功
 214     }
 215 }
 216 
 217 /*按照货物重量从高到低排序*/
 218 void sortweight(Graph* mygraph)
 219 {
 220     bool flag = true;
 221     for (int i = 1; i <= goodsnum && flag; i++) {
 222         flag = false;
 223         for (int j = goodsnum - 1; j > i; j--) {
 224             if (mygraph->out[j]->goodweight > mygraph->out[j - 1]->goodweight) {
 225                 swap(mygraph->out[j], mygraph->out[j - 1]);
 226                 flag = true;
 227             }
 228         }
 229     }
 230 }
 231 
 232 /*用Dijkstra算法求两站之间的最短路径*/
 233 route* Dijkstra(Graph* mygraph, string start, string end)
 234 {
 235     int n = mygraph->nodenum;                      //站点数
 236     int spoint = change(mygraph, start);
 237     int epoint = change(mygraph, end);
 238     int dist[maxnum] = { 0 };                      //存放各点到起点的最短距离
 239     for (int i = 1; i <= n; i++) {
 240         dist[i] = INF;
 241     }
 242     route* list = new route;                       //记录运送路径
 243     list->process = start;
 244     list->next = nullptr;
 245     route* first = list;
 246     int min, k, tem;
 247     int foot[maxnum] = { 0 };                      //记录站点是否已经被选取
 248     int prev[maxnum] = { 0 };                      //前驱节点,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。                                                
 249     foot[spoint] = 1;                              //spoint是出发节点,该位置标识为1
 250     dist[spoint] = 0;                              //spoint是出发节点,距离起点的距离是0
 251     /*初始化*/
 252     Node* f = mygraph->headnode[spoint];
 253     while (f != nullptr) {
 254         int fm = change(mygraph, f->index);
 255         dist[fm] = f->weight;
 256         prev[fm] = spoint;
 257         f = f->next;
 258     }
 259     /*最多遍历n-1次寻找end点*/
 260     for (int i = 1; i < n; i++) {
 261         min = INF;
 262         for (int j = 1; j <= n; j++) {
 263             if (foot[j] == 0 && dist[j] < min) {
 264                 min = dist[j];
 265                 k = j;
 266             }
 267         }
 268         if (k == epoint) break;                                           //找到了目标站点
 269         foot[k] = 1;
 270         Node* fi = mygraph->headnode[k];
 271         int inx[maxnum] = { 0 };                                      //用来存放是否与第k结点联通  inx[]=1代表联通
 272         int wei[maxnum] = { 0 };                                      //用来存放与k结点之间的权值
 273         while (fi != nullptr) {
 274             inx[change(mygraph, fi->index)] = 1;
 275             wei[change(mygraph, fi->index)] = fi->weight;
 276             fi = fi->next;
 277         }
 278         /* 修正当前最短路径和前驱顶点*/
 279         for (int j = 1; j <= n; j++) {
 280             if (inx[j] == 1)  tem = wei[j] + dist[k];                  //若j与k联通,则tem=weight,否者为inf
 281             else   tem = INF;
 282 
 283             if (foot[j] == 0 && tem < dist[j]) {
 284                 dist[j] = tem;
 285                 prev[j] = k;
 286             }
 287         }
 288     }
 289     int back = epoint;
 290     while (back != spoint) {                                               //倒插法生成路径链表
 291         route* newlist = new route;
 292         newlist->process = mygraph->name[back];                            //back点对应的站名称
 293 
 294         Node* findtrail = new Node;
 295         findtrail = mygraph->headnode[prev[back]];
 296         while (findtrail->index != mygraph->name[back]) {
 297             findtrail = findtrail->next;
 298         }
 299         newlist->trail = findtrail->rname;                                 //到达该站点的轨道
 300         newlist->next = list->next;
 301         list->next = newlist;
 302         back = prev[back];
 303     }
 304     return first;
 305 }
 306 
 307 /*利用dijkstra求带有必经站点的路径*/
 308 route* joint(Graph* newgraph, int i)
 309 {
 310     route* first = new route;
 311     route* second = new route;
 312     route* third = new route;
 313     route* forth = new route;
 314 
 315     int mid = newgraph->out[i]->midstation.size();
 316     //分段求,再拼接
 317 
 318     if (mid == 1) {
 319         first = Dijkstra(newgraph, newgraph->out[i]->startstation, newgraph->out[i]->midstation[0]);
 320         second = Dijkstra(newgraph, newgraph->out[i]->midstation[0], newgraph->out[i]->endstation);
 321         //拼接
 322         route* p1 = new route;
 323         p1 = first;
 324         while (p1->next) {
 325             p1 = p1->next;
 326         }
 327         p1->next = second->next;
 328         return first;
 329     }
 330     if (mid == 2) {
 331         first = Dijkstra(newgraph, newgraph->out[i]->startstation, newgraph->out[i]->midstation[0]);
 332         second = Dijkstra(newgraph, newgraph->out[i]->midstation[0], newgraph->out[i]->midstation[1]);
 333         third = Dijkstra(newgraph, newgraph->out[i]->midstation[1], newgraph->out[i]->endstation);
 334         route* p1 = new route;
 335         route* p2 = new route;
 336         p1 = first;
 337         p2 = second;
 338         while (p1->next) {
 339             p1 = p1->next;
 340         }
 341         p1->next = second->next;
 342         while (p2->next) {
 343             p2 = p2->next;
 344         }
 345         p2->next = third->next;
 346         return first;
 347     }
 348 
 349     if (mid == 3) {
 350         first = Dijkstra(newgraph, newgraph->out[i]->startstation, newgraph->out[i]->midstation[0]);
 351         second = Dijkstra(newgraph, newgraph->out[i]->midstation[0], newgraph->out[i]->midstation[1]);
 352         third = Dijkstra(newgraph, newgraph->out[i]->midstation[1], newgraph->out[i]->midstation[2]);
 353         forth = Dijkstra(newgraph, newgraph->out[i]->midstation[2], newgraph->out[i]->endstation);
 354         route* p1 = new route;
 355         route* p2 = new route;
 356         route* p3 = new route;
 357         p1 = first;
 358         p2 = second;
 359         p3 = third;
 360         while (p1->next) {
 361             p1 = p1->next;
 362         }
 363         p1->next = second->next;
 364         while (p2->next) {
 365             p2 = p2->next;
 366         }
 367         p2->next = third->next;
 368         while (p3->next) {
 369             p3 = p3->next;
 370         }
 371         p3->next = forth->next;
 372         return first;
 373     }
 374 }
 375 
 376 //判断是否有回环
 377 bool isloopbock(route* list)
 378 {
 379     route* pt = new route;
 380     route* pe = new route;
 381     pt = list;
 382     while (pt->next != nullptr) {
 383         pe = pt->next;
 384         while (pe != nullptr)
 385         {
 386             if (pt->process == pe->process) {
 387                 return true;             //有环
 388             }
 389             pe = pe->next;
 390         }
 391         pt = pt->next;
 392     }
 393     return false;                    //没环
 394 }
 395 
 396 
 397 /*调整运输成功的路径权值*/
 398 void adjust(Graph* mygraph, route* list)
 399 {
 400     route* t = new route;
 401     t = list;
 402     Node* nod = new Node;
 403     int fir;
 404     string sec;
 405     while (t->next) {
 406         fir = change(mygraph, t->process);
 407         sec = t->next->process; 
 408         nod = mygraph->headnode[fir];
 409         while (nod) {
 410             if (nod->index == sec) {
 411                 nod->weight++;
 412                 break;
 413             }
 414             nod = nod->next;
 415         }
 416         t = t->next;
 417     }
 418 }
 419 
 420 /*判断两站点的可用轨道*/
 421 int usefultrail(Graph* mygraph, route* list, int w)                      //输入两个站点,输出其中可用的轨道
 422 {
 423     int stapoint;
 424     route* l = new route;
 425     for (int i = 1; i <= carnum; i++) {
 426         bool sign = true;                                                //标志位,如果其true则表示该节列车可用否则不可用
 427         l = list->next;
 428         while (l != nullptr) {
 429             stapoint = echange(mygraph, l->trail);
 430             if (mygraph->edgeuse[stapoint]->car[i] > 0) {                //表示该节车厢(i)上已经有货物
 431                 sign = false;                                           //该节车厢不可用
 432                 break;
 433             }
 434             l = l->next;
 435         }
 436         if (sign == true) {                                              //sign是真,表示该节车厢可以运输,接下来便将其占用
 437             l = list->next;
 438             while (l != nullptr) {
 439                 stapoint = echange(mygraph, l->trail);
 440                 mygraph->edgeuse[stapoint]->car[i] = mygraph->out[w]->goodweight; //货物重量放进车厢
 441                 mygraph->edgeuse[stapoint]->gname[i] = mygraph->out[w]->name;     //货物名称放进去
 442                 l = l->next;
 443             }
 444             delete l;                                                   //删除指针
 445             return i;                                                   //返回该节车厢
 446         }
 447     }
 448     return 0;                                                           //返回零表示该趟列车不可运输
 449 }
 450 
 451 /*判断两个同源同宿的货物是否可以打包*/
 452 bool istogether(Graph* mygraph, int old, int ne)        //old代表已经占位的第old个货物,ne代表新来的第ne个货物(不一样)
 453 {
 454     for (int i = 1; i <= success[old][0]; i++) {
 455         int g = echange(mygraph, outroad[old][i]);    //轨道的编号
 456         int j = success[old][i];                     //列车编号
 457         if (mygraph->edgeuse[g]->car[j] + mygraph->out[ne]->goodweight > carweight) {//这一段超重了装不了了
 458             return false;
 459         }
 460     }
 461     return true;
 462 }
 463 
 464 /*找经过某个站的某货物除当前轨道的另一条轨道通往的站点**/
 465 // fine(图,站点编号,当前轨道名称,货物名称,车厢编号)
 466 string fine(Graph* mygraph, int spoint, string lname, string name,int i)
 467 {
 468     Node* no = new Node;
 469     no= mygraph->headnode[spoint];
 470     while (no) {
 471         int g = echange(mygraph, no->rname);
 472         if (mygraph->edgeuse[g]->gname[i] == name ) { //找到装有该货物的一节轨道
 473             if (no->rname != lname) {    //不是当前轨道,那就是另外一条轨道,就找到了
 474                 return no->index;
 475             }
 476         }
 477         no = no->next;
 478     }
 479     return name;
 480 }
 481 
 482 /*是否可以使用分拣员换车*/
 483 bool changecar(Graph* mygraph, route* list, int w)
 484 {
 485     double weight = mygraph->out[w]->goodweight;         //该货物重量
 486     if (weight > carweight) return false;        //超重失败
 487     
 488     int delrail[50][2];                                 //初始化一个二维数组,1.代表轨道  2代表车厢 
 489     int delnum[50][2];                      //初始化一个二维数组,第一列存放需要去掉分拣员的站点编号,第二列存放减去分拣员得数量
 490     string goname[70];                     //存放占用了新车厢的货物的名字
 491     int gocar[70][2];                     //存放第几节轨道的第几个车厢新增了货物,第一列轨道,第二列车厢
 492     int go=0;                             //用于计数
 493     int spoint, lpoint; 
 494     route* l = new route;
 495     route* s = new route;
 496     int whichcar = 1;
 497     int wh = 0;                                         //存放第wh个车厢编号
 498     int del = 0;                                        //存放第del个需要去掉分拣员的车厢编号
 499     s = list;
 500     l = list->next;
 501     
 502     spoint = change(mygraph, s->process);                //站的编号
 503     lpoint = echange(mygraph, l->trail);                 //轨道的编号
 504     //先找第一段的车厢编号
 505     for (int j = 1; j <= carnum; j++) {
 506         if (mygraph->edgeuse[lpoint]->car[j] + weight <= carweight) { //该节车厢能装下
 507             if (mygraph->edgeuse[lpoint]->car[j] == 0) {     //如果是空车厢,安排,需要一个分拣员
 508                 if (mygraph->worker[spoint] >= 1) {
 509                     whichcar = j;                                   //表示该行车厢是货物装上去的车厢
 510                     mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在j号车厢上
 511                     delrail[wh][0] = lpoint;
 512                     delrail[wh][1] = whichcar;
 513                     goname[++go] = mygraph->out[w]->name;   //存放名字
 514                     gocar[go][0] = lpoint;                  //第几个轨道
 515                     gocar[go][1] = whichcar;                //第几个车厢
 516                     
 517                     delnum[++del][0] = spoint;
 518                     delnum[del][1] = 1;       //起点只用减一个
 519                     /******/         //要记录下是哪个工位安排分拣员
 520                     mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, l->process);  //记录站点
 521                     mygraph->headnode[spoint]->delcar[1][1] = whichcar;    //记录车厢号用于安排分拣员
 522 
 523                     s = s->next;
 524                     l = l->next;
 525                     break;
 526                 }
 527             }
 528             else {            //如果不是空车厢
 529                 Node* fnod = new Node;
 530                 fnod = mygraph->headnode[spoint];
 531                 while (fnod) {
 532                     if (fnod->index == l->process) {    //找到了该轨道通往的下一站点
 533                         break;
 534                     }
 535                     fnod = fnod->next;
 536                 }
 537 
 538                 if (fnod->handlers[j] == 1) {   //该节车厢对应的站点有分拣员,直接上货,不用安排分拣员
 539                     whichcar = j;
 540                     mygraph->out[w]->listnum[++wh] = whichcar;
 541                     delrail[wh][0] = lpoint;
 542                     delrail[wh][1] = whichcar;
 543                     s = s->next;
 544                     l = l->next;
 545                     break;
 546                 }
 547                 if (fnod->handlers[j] == 0) {   //该节车厢对应的站点没有分拣员,说明有货物通过,要先找到该货物是从哪个站发来的
 548                     if (mygraph->worker[spoint] >= 2) {   //需要两个分拣员
 549                         string hname = mygraph->edgeuse[lpoint]->gname[j];  //已经在车上的货物名字
 550                         string ssname = fine(mygraph, spoint, l->trail, hname, j); //上一个站的名字
 551                         if (ssname != hname) {
 552                             whichcar = j;
 553                             mygraph->out[w]->listnum[++wh] = whichcar;
 554                             delrail[wh][0] = lpoint;
 555                             delrail[wh][1] = whichcar;
 556                             delnum[++del][0] = spoint;
 557                             delnum[del][1] = 2;      //要用两个
 558                             /**********/// 记录需要安排分拣员的站点
 559                             mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, l->process);  //记录站点
 560                             mygraph->headnode[spoint]->delcar[1][1] = whichcar;    //记录车厢号
 561                             mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, ssname);  //记录站点
 562                             mygraph->headnode[spoint]->delcar[2][1] = whichcar;    //记录车厢号
 563                             s = s->next;
 564                             l = l->next;
 565                             break;
 566                         }
 567                     }
 568                 }
 569             }
 570         }
 571         if (j == carnum) {
 572             return false;                            //第一段路轨都没有可用车厢,判定失败
 573         }
 574     }
 575     
 576     //开始往后运输
 577     while (l != nullptr) {
 578         spoint = change(mygraph, s->process);
 579         lpoint = echange(mygraph, l->trail);
 580 
 581         //先考虑能否沿着当前路径不消耗分拣员继续运输
 582         if (mygraph->edgeuse[lpoint]->car[whichcar] + weight <= carweight) {   //表示这一段有可能还可以继续走,不用换车厢
 583            
 584             /*分两种大情况,该货物是包车的还是拼车来的*/
 585             if (mygraph->edgeuse[echange(mygraph, s->trail)]->car[whichcar] == 0) {//上一段是空的过来的,那么下一段要么是空,要么是有分拣员,可以继续运输
 586                 if (mygraph->edgeuse[lpoint]->car[whichcar] == 0) { //这一段还是空,不用分拣员,继续走
 587                     mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在j号车厢上
 588                     delrail[wh][0] = lpoint;
 589                     delrail[wh][1] = whichcar;
 590                     goname[++go] = mygraph->out[w]->name;   //存放名字
 591                     gocar[go][0] = lpoint;                  //第几个轨道
 592                     gocar[go][1] = whichcar;                //第几个车厢
 593                     
 594                     s = s->next;
 595                     l = l->next;
 596                     continue;
 597                 }
 598             }
 599             else {  //上一段是拼车的,下一段除非和上一段的货物还继续同行,可以不用换乘,不用消耗分拣员
 600                 int nowt = echange(mygraph, s->trail);
 601                 if (mygraph->edgeuse[lpoint]->gname[whichcar] == mygraph->edgeuse[nowt]->gname[whichcar]) {   //继续同行
 602                     mygraph->out[w]->listnum[++wh] = whichcar;
 603                     delrail[wh][0] = lpoint;
 604                     delrail[wh][1] = whichcar;
 605                     s = s->next;
 606                     l = l->next;
 607                     continue;
 608                 }
 609             }
 610         }
 611         //需换车厢了,也要分两种情况,上一段是包车还是拼车来的
 612         if (mygraph->edgeuse[echange(mygraph, s->trail)]->car[whichcar] == 0) {  //上一段是空着过来的
 613             for (int i = 1; i <= carnum; i++) {
 614                 
 615                 if (mygraph->edgeuse[lpoint]->car[i] + weight <= carweight) {//该节车厢装,又分两种情况
 616                     if (mygraph->edgeuse[lpoint]->car[i] == 0) { //①该节车厢是空的,消耗两个分拣员
 617                         if (mygraph->worker[spoint] >= 2) {
 618                             //记录下需要安排分拣员得站点轨道
 619                             string shname;   //上一站的名称
 620                             Node* fno = new Node;
 621                             fno = mygraph->headnode[spoint];
 622                             while (fno) {
 623                                 if (fno->rname == s->trail) {  //找到了该站点
 624                                     shname = fno->index;       //记录站点名称
 625                                     break;
 626                                 }
 627                                 fno = fno->next;
 628                             }
 629                             mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, l->process);  //记录下一站点
 630                             mygraph->headnode[spoint]->delcar[1][1] = i;                         //记录将要乘坐的车厢号
 631                             mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, shname);   //记录上一站点
 632                             mygraph->headnode[spoint]->delcar[2][1] = whichcar;                  //记录过来的车厢号
 633 
 634                             whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 635                             mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 636                             delrail[wh][0] = lpoint;
 637                             delrail[wh][1] = whichcar;
 638                             goname[++go] = mygraph->out[w]->name;   //存放名字,用于存放新开辟轨道的货物
 639                             gocar[go][0] = lpoint;                  //第几个轨道
 640                             gocar[go][1] = whichcar;                //第几个车厢
 641                            
 642                             delnum[++del][0] = spoint;
 643                             delnum[del][1] = 2;                     //减2个
 644                             s = s->next;
 645                             l = l->next;
 646 
 647                             break;
 648                         }
 649                     }
 650                     if (mygraph->edgeuse[lpoint]->car[i] > 0) {   //②该节车厢装有货物,至少消耗一个
 651                         if (mygraph->worker[spoint] >= 1) {
 652                             Node* fno1 = new Node;
 653                             fno1 = mygraph->headnode[spoint];
 654                             while (fno1) {
 655                                 if (fno1->index == l->process) {
 656                                     break;
 657                                 }
 658                                 fno1 = fno1->next;
 659                             }
 660                             if (fno1->handlers[i] == 1) {  //该工位有人,可以运输,只需用一个分拣员
 661                                 string shname;   //上一站的名称
 662                                 Node* fno = new Node;
 663                                 fno = mygraph->headnode[spoint];
 664                                 while (fno) {
 665                                     if (fno->rname == s->trail) {  //找到了该站点
 666                                         shname = fno->index;       //记录站点名称
 667                                         break;
 668                                     }
 669                                     fno = fno->next;
 670                                 }
 671                                 mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, shname);  //记录上一站点
 672                                 mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 673                                 whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 674                                 mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 675                                 delrail[wh][0] = lpoint;
 676                                 delrail[wh][1] = whichcar;
 677                                 delnum[++del][0] = spoint;
 678                                 delnum[del][1] = 1;                     //减1个
 679                                 s = s->next;
 680                                 l = l->next;
 681 
 682                                 break;
 683                             }
 684                             if (fno1->handlers[i] == 0) {
 685                                 if (mygraph->worker[spoint] >= 3) {   //需要三个分拣员
 686                                     string shname;   //上一站的名称
 687                                     Node* fno = new Node;
 688                                     fno = mygraph->headnode[spoint];
 689                                     while (fno) {
 690                                         if (fno->rname == s->trail) {  //找到了该站点
 691                                             shname = fno->index;       //记录站点名称
 692                                             break;
 693                                         }
 694                                         fno = fno->next;
 695                                     }
 696                                     mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, shname);  //记录下一站点
 697                                     mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 698                                     //找即将合并的货物的上一站
 699                                     string hname = mygraph->edgeuse[lpoint]->gname[i];  //已经在车上的货物名字
 700                                     string sname = fine(mygraph, spoint, l->trail, hname, i); //上一个站的名字
 701                                     
 702                                     whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 703                                     mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 704                                     delrail[wh][0] = lpoint;
 705                                     delrail[wh][1] = whichcar;
 706                                     delnum[++del][0] = spoint;
 707                                     delnum[del][1] = 3;                     //减3个
 708                                     mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, sname);  //记录下一站点
 709                                     mygraph->headnode[spoint]->delcar[2][1] = whichcar;
 710                                     mygraph->headnode[spoint]->delcar[3][0] = change(mygraph, l->process);  //记录下一站点
 711                                     mygraph->headnode[spoint]->delcar[3][1] = whichcar;
 712 
 713                                     s = s->next;
 714                                     l = l->next;
 715                                     break;
 716                                 }
 717 
 718                             }
 719                         }
 720                     }
 721                 }
 722                 if (i == carnum) {
 723                     return false;                           //该条轨道没有可用车厢,断路 
 724                 }
 725             }
 726 
 727         }
 728         else{   //货物是拼车过来的
 729             Node* fno = new Node;
 730             fno = mygraph->headnode[spoint];
 731             while (fno) {
 732                 if (fno->rname == s->trail) {  //找到了该站点
 733                     break;
 734                 }
 735                 fno = fno->next;
 736             }
 737             for (int i = 1; i <= carnum; i++) {
 738                 if (mygraph->edgeuse[lpoint]->car[i] + weight <= carweight) {
 739                     if (fno->handlers[whichcar] == 1) {    //拼车一起或来的货到这停了
 740                         if (mygraph->edgeuse[lpoint]->car[i] == 0 && mygraph->worker[spoint] >= 1) {  //下一轨道是空,只需一个分拣员
 741                             mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, l->process);  //记录下一站点
 742                             mygraph->headnode[spoint]->delcar[1][1] = i;
 743                             whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 744                             mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 745                             delrail[wh][0] = lpoint;
 746                             delrail[wh][1] = whichcar;
 747                             goname[++go] = mygraph->out[w]->name;   //存放名字,用于存放新开辟轨道的货物
 748                             gocar[go][0] = lpoint;                  //第几个轨道
 749                             gocar[go][1] = whichcar;                //第几个车厢
 750                             
 751                             delnum[++del][0] = spoint;
 752                             delnum[del][1] = 1;                     //减1个
 753                             s = s->next;
 754                             l = l->next;
 755                             break;
 756                         }
 757                         else {     //下一轨道有货物 ①起点  ②路经点
 758                             Node* od = new Node;
 759                             od = mygraph->headnode[spoint];
 760                             while (od) {
 761                                 if (od->index == l->process) {
 762                                     break;
 763                                 }
 764                                 od = od->next;
 765                             }
 766                             if (od->handlers[i] == 1) {  //这里有一个分拣员,则直接上,下一个是一个货物起点,不用消耗分拣员
 767                                 whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 768                                 mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 769                                 delrail[wh][0] = lpoint;
 770                                 delrail[wh][1] = whichcar;
 771                                 s = s->next;
 772                                 l = l->next;
 773 
 774                                 break;
 775                             }
 776                             else {  //这是另一个货物的途经点,需要两个分拣员
 777                                 if (mygraph->worker[spoint] >= 2) {
 778                                     string sname = mygraph->edgeuse[lpoint]->gname[i];  //另一个货物的名字
 779                                     
 780                                     string lstation = fine(mygraph, spoint, l->trail, sname, i);     //另一个货物上一个站的名字
 781                                     whichcar = i;
 782                                     mygraph->out[w]->listnum[++wh] = whichcar;
 783                                     delrail[wh][0] = lpoint;
 784                                     delrail[wh][1] = whichcar;
 785                                     delnum[++del][0] = spoint;
 786                                     delnum[del][1] = 2;      //要用两个
 787                                     // 记录需要安排分拣员的站点
 788                                     mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, l->process);  //记录站点
 789                                     mygraph->headnode[spoint]->delcar[1][1] = whichcar;    //记录车厢号
 790                                     mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, lstation);  //记录站点
 791                                     mygraph->headnode[spoint]->delcar[2][1] = whichcar;    //记录车厢号
 792                                     s = s->next;
 793                                     l = l->next;
 794 
 795                                     break;
 796                                 }
 797                             } 
 798                         }
 799 
 800                     }
 801                     if (fno->handlers[whichcar] == 0) {                  //拼车一起或来的货到这还要继续走
 802                         if (mygraph->edgeuse[lpoint]->car[i] == 0) {  //下一车厢是空,需要3个分拣员
 803                             if (mygraph->worker[spoint] >= 3) {
 804                                 string name = mygraph->edgeuse[echange(mygraph, s->trail)]->gname[whichcar];
 805                                 string nextst = fine(mygraph, spoint, s->trail, name, whichcar);
 806                                 mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, nextst);  //记录下一站点
 807                                 mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 808                                 mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, fno->index);
 809                                 mygraph->headnode[spoint]->delcar[2][1] = whichcar;
 810                                 mygraph->headnode[spoint]->delcar[3][0] = change(mygraph, l->process);
 811                                 mygraph->headnode[spoint]->delcar[3][1] = i;
 812                                 whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 813                                 mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 814                                 delrail[wh][0] = lpoint;
 815                                 delrail[wh][1] = whichcar;
 816                                 goname[++go] = mygraph->out[w]->name;   //存放名字,用于存放新开辟轨道的货物
 817                                 gocar[go][0] = lpoint;                  //第几个轨道
 818                                 gocar[go][1] = whichcar;                //第几个车厢
 819 
 820                                 delnum[++del][0] = spoint;
 821                                 delnum[del][1] = 3;                     //减3个
 822                                 s = s->next;
 823                                 l = l->next;
 824 
 825                                 break;
 826                             }
 827                         }
 828                         else {   //下一个车厢不是空,分两种情况 ①是起点  ②是途经点
 829                             Node* od = new Node;
 830                             od = mygraph->headnode[spoint];
 831                             while (od) {
 832                                 if (od->index == l->process) {
 833                                     break;
 834                                 }
 835                                 od = od->next;
 836                             }
 837                             if (od->handlers[i] == 1) {  //这里有一个分拣员,则直接上,下一个是一个货物起点,需要两个分拣员
 838                                 if (mygraph->worker[spoint] >= 2) {
 839                                     string name = mygraph->edgeuse[echange(mygraph, s->trail)]->gname[whichcar];
 840                                     string nextst = fine(mygraph, spoint, s->trail, name, whichcar);
 841                                     mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, nextst);  //记录下一站点
 842                                     mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 843                                     mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, fno->index);
 844                                     mygraph->headnode[spoint]->delcar[2][1] = whichcar;
 845 
 846                                     whichcar = i;                                   //表示该行车厢是货物装上去的车厢
 847                                     mygraph->out[w]->listnum[++wh] = whichcar;      //第wh个轨道装在i号车厢上
 848                                     delrail[wh][0] = lpoint;
 849                                     delrail[wh][1] = whichcar;
 850                                     delnum[++del][0] = spoint;
 851                                     delnum[del][1] = 2;                     //减2个
 852                                     s = s->next;
 853                                     l = l->next;
 854 
 855                                     break;
 856                                 }
 857                             }
 858                             else {           //下一个站点是另一个货物的途经点,需要4个拣货员
 859                                 if (mygraph->worker[spoint] >= 4) {
 860                                     string name = mygraph->edgeuse[echange(mygraph, s->trail)]->gname[whichcar];
 861                                     string nextst = fine(mygraph, spoint, s->trail, name, whichcar);
 862                                     mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, nextst);  //记录下一站点
 863                                     mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 864                                     mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, fno->index);
 865                                     mygraph->headnode[spoint]->delcar[2][1] = whichcar;
 866 
 867                                     string sname = mygraph->edgeuse[lpoint]->gname[i];  //另一个货物的名字
 868                                     string lstation = fine(mygraph, spoint, l->trail, sname,i);     //另一个货物上一个站的名字
 869                                     mygraph->headnode[spoint]->delcar[3][0] = change(mygraph, l->process);  //记录站点
 870                                     mygraph->headnode[spoint]->delcar[3][1] = i;    //记录车厢号
 871                                     mygraph->headnode[spoint]->delcar[4][0] = change(mygraph, lstation);  //记录站点
 872                                     mygraph->headnode[spoint]->delcar[4][1] = i;    //记录车厢号
 873                                     whichcar = i;
 874                                     mygraph->out[w]->listnum[++wh] = whichcar;
 875                                     delrail[wh][0] = lpoint;
 876                                     delrail[wh][1] = whichcar;
 877                                     delnum[++del][0] = spoint;
 878                                     delnum[del][1] = 4;      //要用4个
 879                                     s = s->next;
 880                                     l = l->next;
 881 
 882                                     break;
 883                                 }
 884                             }
 885                         }
 886                     }
 887                 }
 888                 if (i == carnum) {
 889                     return false;                           //该条轨道没有可用车厢,断路 
 890                 }
 891             }
 892         }
 893     }
 894     spoint = change(mygraph, s->process);     //到达终点站,也要分类讨论,首先还是分两大类,专车到或者拼车
 895     lpoint = echange(mygraph, s->trail);
 896     Node* qm = new Node;
 897     qm = mygraph->headnode[spoint];
 898     while (qm) {       
 899         if (qm->rname==s->trail) {         //找倒数第二个站点
 900             break;
 901         }
 902         qm = qm->next;
 903     }
 904     //int lastat = change(mygraph, qm->index);  //倒数第二个站点编号
 905     bool issuccess = true;              //标志位,true代表成功
 906     if (mygraph->edgeuse[lpoint]->car[whichcar] == 0) {   //是专车过来的,耗费一个分拣员
 907         if (mygraph->worker[spoint] >= 1) {
 908             delnum[++del][0] = spoint;
 909             delnum[del][1] = 1;      //要用1个
 910             mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, qm->index);  //记录上一站点
 911             mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 912         }
 913         else {
 914             issuccess = false;
 915         }
 916     }
 917     else {    //拼车过来,再分两种情况讨论 ①该站点是同行货物的终点站,有分拣员下货  ②该站点是途经站,没有分拣员
 918         if (qm->handlers[whichcar]==0) {        //没有分拣员站岗,需要安排两个分拣员
 919             if (mygraph->worker[spoint] >= 2) {
 920                 delnum[++del][0] = spoint;
 921                 delnum[del][1] = 2;      //要用2个
 922                 mygraph->headnode[spoint]->delcar[1][0] = change(mygraph, qm->index);  //记录上一站点
 923                 mygraph->headnode[spoint]->delcar[1][1] = whichcar;
 924 
 925                 string name = mygraph->edgeuse[echange(mygraph, s->trail)]->gname[whichcar];
 926                 string nextst = fine(mygraph, spoint, s->trail, name, whichcar);
 927                 mygraph->headnode[spoint]->delcar[2][0] = change(mygraph, nextst);  //记录下一站点
 928                 mygraph->headnode[spoint]->delcar[2][1] = whichcar;
 929             }
 930             else {
 931                 issuccess = false;
 932             }
 933         }
 934     }
 935     if (issuccess) {// 操作
 936         Node* ha = new Node;
 937         for (int i = 1; i <= del; i++) {
 938             mygraph->worker[delnum[i][0]] -= delnum[i][1]; //扣除分拣员
 939             
 940 
 941             for (int j = 1; j <= delnum[i][1]; j++) {     //安放分拣员
 942                 ha = mygraph->headnode[delnum[i][0]];           //出发站点
 943                 int h = ha->delcar[j][0];  //目标站点编号
 944                 int a = ha->delcar[j][1];  //车厢编号
 945                 while (ha) {
 946                     if (ha->index == mygraph->name[h]) {
 947                         ha->handlers[a] = 1;
 948                         break;
 949                     }
 950                     ha = ha->next;
 951                 }
 952             }
 953         }
 954         /*安放货物*/
 955         for (int i = 1; i <= wh; i++) {
 956             mygraph->edgeuse[delrail[i][0]]->car[delrail[i][1]] += weight;
 957         }
 958         /*给新开辟的车厢装货物名字*/
 959         for (int i = 1; i <= go; i++) {
 960             mygraph->edgeuse[gocar[i][0]]->gname[gocar[i][1]] = goname[i];  //装上名字
 961         }
 962         mygraph->out[w]->listnum[0] = wh;          //路径总长
 963         return true;
 964     }
 965    
 966     return false;
 967 }
 968 
 969 
 970 /*起点和终点人数是否足够*/
 971 bool transfom(Graph* mygraph, Goods* good, route* list)       //只看起点终点,a代表第a节车厢
 972 {
 973     int s = good->wcar;
 974     if (good->goodweight > carweight) return false;        //超重
 975     int stapoint, endpoint;
 976     route* l = new route;
 977     l = list;
 978     stapoint = change(mygraph, l->process);         //第一个站点编号
 979     string nname = l->next->process;                //第二个站点的名称
 980 
 981     while (l->next->next != nullptr) {
 982         l = l->next;
 983     }
 984     string stname = l->process;                   //倒数第二个站的名称
 985     l = l->next;
 986     endpoint = change(mygraph, l->process);       //最后一站的编号
 987     if (mygraph->worker[stapoint] >=1  && mygraph->worker[endpoint] >= 1) {
 988         mygraph->worker[stapoint]--;
 989         mygraph->worker[endpoint]--;
 990 
 991         Node* b = mygraph->headnode[stapoint];           //首站点找到了
 992         while (b != nullptr) {                           //寻找第二个站点
 993             if (b->index == nname) {
 994                 b->handlers[s] = 1;                     //起点站该工位站一个服务员
 995                 break;
 996             }
 997             b = b->next;
 998         }
 999 
1000         Node* c = mygraph->headnode[endpoint];         //找到终点站
1001         while (c != nullptr) {                         //找倒数第二个站
1002             if (c->index == stname) {
1003                 c->handlers[s] = 1;                    //终点站该工位站一个服务员
1004                 break;
1005             }
1006             c = c->next;
1007         }
1008         return true;
1009     }
1010     else {
1011         return false;
1012     }
1013 }
1014 
1015 
1016 
1017 int main()
1018 {
1019     Graph* newgraph = new Graph;
1020     newgraph = buildgraph();
1021     inishgood(newgraph);
1022     sortweight(newgraph);                              //货物排下序
1023 
1024     int failnum = 1;                                   //记录失败得货物
1025     int fail[maxnum] = {0};                                  //运送失败的货物
1026     int count = 0;                                     //成功的个数
1027 
1028     int z = 0;
1029     int mn[maxnum] = { 0 };
1030     static int allnum = 0;                              //总共占了多少车厢
1031     int m[maxnum] = { 0 };                              //记录成功占用车厢的货物编号
1032     
1033     for (int i = 1; i <= goodsnum; i++) {
1034         if (newgraph->out[i]->midstation[0] == "null") {                              //表示该货物不中转
1035             //如果前面有相同的路径,并且上一个成功了,则判断是否可以直接和上一个成功的路径相同
1036             int d = count;                //先记录一下当前成功的货物
1037             for (int j = 1; j <= allnum; j++) {
1038                 if (newgraph->out[i]->startstation == newgraph->out[m[j]]->startstation && newgraph->out[i]->endstation == newgraph->out[m[j]]->endstation|| newgraph->out[i]->startstation == newgraph->out[m[j]]->endstation && newgraph->out[i]->endstation == newgraph->out[m[j]]->startstation) {
1039                     int n = newgraph->out[m[j]]->nows;
1040                     if (istogether(newgraph, n, i)) {          //可以打包装上
1041                         count++;
1042                         for (int j = 0; j <= success[n][0]; j++) {
1043                             success[count][j] = success[n][j];
1044                         }
1045                         outroad[count][0] = newgraph->out[i]->name;
1046                         for (int j = 1; j <= success[count][0]; j++) {
1047                             outroad[count][j] = outroad[n][j];
1048                             int g = echange(newgraph, outroad[count][j]);    //轨道的编号
1049                             int l = success[count][j];                       //该节轨道车厢的编号
1050                             newgraph->edgeuse[g]->car[l] += newgraph->out[i]->goodweight;  //装货
1051                         }
1052                         loseweight = loseweight - newgraph->out[i]->goodweight;
1053                         break;
1054                     }
1055                 }
1056             }
1057             if (d < count) continue;     //如果count变大了,说明上面的循环找到了转运成功的货物
1058 
1059             route* a = new route;
1060             a = Dijkstra(newgraph, newgraph->out[i]->startstation, newgraph->out[i]->endstation);
1061             int n = usefultrail(newgraph, a, i);
1062             if (n != 0) {                                                  // 表示该条路经有空闲车厢,并且货物已经装上 
1063                 
1064                 newgraph->out[i]->wcar = n;                               //记录一下其占用的车厢号
1065                 if (transfom(newgraph, newgraph->out[i], a)) {            //再看起点和终点分拣员是否足够
1066                     //将对应的工位放上拣货员
1067 
1068                     adjust(newgraph, a);
1069                     count++;
1070                     outroad[count][0] = newgraph->out[i]->name;
1071                     int tal = 0;                                                 //表示该路径经过了多少轨道 
1072                     route* t = a->next;
1073                     while (t != nullptr) {
1074                         outroad[count][++tal] = t->trail;
1075                         t = t->next;
1076                     }
1077                     success[count][0] = tal;
1078                     for (int j = 1; j <= tal; j++) {
1079                         success[count][j] = n;
1080                     }
1081                     delete t;
1082                     loseweight = loseweight - newgraph->out[i]->goodweight;                    //运输成功则减去该部分重量
1083 
1084                     m[++allnum] = i;                        //该货物开辟了新的路径,记录下编号
1085                     newgraph->out[i]->nows = count;
1086                 }
1087                 else {
1088                     fail[failnum] = i;                                                //因为起点终点分拣员不够失败
1089                     failnum++;
1090                 }
1091             }
1092             else {              //需要换乘
1093                 z++;
1094                 mn[z] = i;                                                       //不能直接到达的先记下来
1095             }
1096         }
1097     }
1098     
1099     int ding = allnum;                                               //分界线
1100     for (int i = 1; i <= z; i++) {
1101         int dd = count;                //先记录一下当前成功的货物
1102         for (int j = ding; j <= allnum; j++) {
1103             if (newgraph->out[mn[i]]->startstation == newgraph->out[m[j]]->startstation && newgraph->out[mn[i]]->endstation == newgraph->out[m[j]]->endstation|| newgraph->out[mn[i]]->startstation == newgraph->out[m[j]]->endstation && newgraph->out[mn[i]]->endstation == newgraph->out[m[j]]->startstation) {
1104                 int n = newgraph->out[m[j]]->nows;
1105                 if (istogether(newgraph, n, mn[i])) {          //可以打包装上
1106                     count++;
1107                     for (int j = 0; j <= success[n][0]; j++) {
1108                         success[count][j] = success[n][j];
1109                     }
1110                     outroad[count][0] = newgraph->out[mn[i]]->name;
1111                     for (int j = 1; j <= success[count][0]; j++) {
1112                         outroad[count][j] = outroad[n][j];
1113                         int g = echange(newgraph, outroad[count][j]);    //轨道的编号
1114                         int l = success[count][j];                       //该节轨道车厢的编号
1115                         newgraph->edgeuse[g]->car[l] += newgraph->out[mn[i]]->goodweight;  //装货
1116                     }
1117                     loseweight = loseweight - newgraph->out[mn[i]]->goodweight;
1118                     break;
1119                 }
1120             }
1121         }
1122         if (dd < count) continue;     //如果count变大了,说明上面的循环找到了转运成功的货物
1123 
1124         route* a = new route;
1125         a = Dijkstra(newgraph, newgraph->out[mn[i]]->startstation, newgraph->out[mn[i]]->endstation);
1126         if (!changecar(newgraph, a, mn[i])) {
1127             fail[failnum] = mn[i];
1128             failnum++;
1129         }
1130         else {
1131             adjust(newgraph, a);
1132             count++;
1133             outroad[count][0] = newgraph->out[mn[i]]->name;
1134             route* t = a->next;
1135             int tall = 0;
1136             while (t != nullptr) {
1137                 outroad[count][++tall] = t->trail;
1138                 t = t->next;
1139             }
1140             success[count][0] = tall;
1141             for (int j = 1; j <= tall; j++) {
1142                 success[count][j] = newgraph->out[mn[i]]->listnum[j];
1143             }
1144             delete t;
1145             loseweight = loseweight - newgraph->out[mn[i]]->goodweight;                    //运输成功则减去该部分重量
1146 
1147             newgraph->out[mn[i]]->allweight = newgraph->out[mn[i]]->goodweight;
1148             m[++allnum] = mn[i];                        //该货物开辟了新的车厢,记录下编号
1149             newgraph->out[mn[i]]->nows = count;
1150         }
1151     }
1152     
1153     for (int i = 1; i <= goodsnum; i++) {
1154         if (newgraph->out[i]->midstation[0] != "null") {
1155             route* a1 = new route;
1156             a1 = joint(newgraph, i);
1157             if (!isloopbock(a1)) {                                                //没环 
1158                 if (changecar(newgraph, a1, i)) {
1159                     adjust(newgraph, a1);
1160                     count++;
1161                     outroad[count][0] = newgraph->out[i]->name;
1162                     route* t = a1->next;
1163                     int tall = 0;
1164                     while (t != nullptr) {
1165                         outroad[count][++tall] = t->trail;
1166                         t = t->next;
1167                     }
1168                     success[count][0] = tall;
1169                     for (int j = 1; j <= tall; j++) {
1170                         success[count][j] = newgraph->out[i]->listnum[j];
1171                     }
1172                     delete t;
1173                     loseweight = loseweight - newgraph->out[i]->goodweight;                    //运输成功则减去该部分重量
1174                 }
1175                 else {
1176                     fail[failnum] = i;
1177                     failnum++;
1178                 }
1179             }
1180             else {
1181                 fail[failnum] = i;
1182                 failnum++;
1183             }
1184         }
1185     }
1186 
1187     //打印总体情况
1188     cout << goodsnum - count << "," << fixed << setprecision(3) << loseweight << endl;
1189     //打印成功的货物,分直接导到和转站
1190 
1191     for (int i = 1; i <= count; i++) {
1192         cout << outroad[i][0] << endl;
1193         int j;
1194         for (j = 1; j < success[i][0]; j++) {
1195             cout << outroad[i][j] << ",";
1196         }
1197         cout << outroad[i][j] << endl;
1198         int a;
1199         for (a = 1; a < success[i][0]; a++) {
1200             cout << success[i][a] << ",";
1201         }
1202         cout << success[i][a] << endl;
1203     }
1204     //打印失败的货物
1205     int i, r;
1206     for (i = 1; i <= goodsnum - count; i++) {
1207         r = fail[i];                              //m表示失败的是第m个货物
1208         cout << newgraph->out[r]->name << endl;
1209         cout << "null" << endl;
1210         cout << "null" << endl;
1211     }
1212     
1213     return 0;
1214 }

View Code

 

版权声明:本文为qandy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/qandy/p/13931328.html