---恢复内容开始---
1 package cn.edu.karel.work.public_transit_problem; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 /** 11 * GreedSolute类 12 * 13 * @author Karel Zuo 14 * @time 2015.6.4 15 * @version 1.0 16 * @description 贪心算法求解公交时刻表和车次链问题 17 */ 18 public class GreedSolute { 19 /** 发车时刻表数据 */ 20 static File forward = new File("D:/mycode/Eclipse/Bus Scheduel Problem/scheduel1/ForwardScheduel/start time.txt"); 21 static File backward = new File("D:/mycode/Eclipse/Bus Scheduel Problem/scheduel1/BackScheduel/start time.txt"); 22 static int sum = 0; 23 24 public static void main(String[] args) throws IOException{ 25 /** 创建时刻表 */ 26 Scheduel scheduel = new Scheduel(); 27 inputForward(scheduel); 28 inputBackward(scheduel); 29 30 /** 固定行车计划 */ 31 ArrayList<TrainsitChain> chain = creatFixedPlan(scheduel); 32 33 /** 可变行车计划 */ 34 //chain = creatVariablePlan(scheduel,chain); 35 } 36 37 /** 38 * 将发车时刻表中的所有车次按照 FIFO规则排序 39 * 40 * @param scheduel 发车时刻表 41 * @return list 排序后的车次序号列表 42 */ 43 public static ArrayList<Integer> sortScheduel(Scheduel scheduel){ 44 /** 排序后的车次序号列表 */ 45 ArrayList<Integer> list = new ArrayList<Integer>(); 46 47 int i = 0; 48 int j = 0; 49 int k = 0; 50 while(i<scheduel.tranListForward.size() && j<scheduel.tranListBack.size()) 51 { 52 if(scheduel.tranListForward.get(i).arriveTime <= scheduel.tranListBack.get(j).arriveTime) 53 { 54 list.add(k, scheduel.tranListForward.get(i).id); 55 i++; 56 } 57 else 58 { 59 list.add(k, scheduel.tranListBack.get(j).id); 60 j++; 61 } 62 k++; 63 } 64 while(i<scheduel.tranListForward.size()) 65 { 66 list.add(k++, scheduel.tranListForward.get(i++).id); 67 } 68 while(j<scheduel.tranListBack.size()) 69 { 70 list.add(k++, scheduel.tranListBack.get(j++).id); 71 } 72 return list; 73 } 74 75 /** 76 * 贪心算法搜索出剩余车次中最长的车次链 77 * 78 * @param list 按照FIFO规则排序后的车次的列表 79 * @param scheduel 用于搜索车次链的发车时刻表 80 * @return chain 搜索到的车次链 81 */ 82 public static TrainsitChain searchChain(ArrayList<Integer> list,Scheduel scheduel){ 83 TrainsitChain chain = new TrainsitChain(); 84 85 /** 以当前剩余车次中的第一个车次为该车次链的首个车次*/ 86 int index = list.get(0); 87 int len = scheduel.tranListForward.size(); 88 if(index >= len ){ 89 index -= len; 90 chain.addTransit(scheduel.tranListBack.get(index)); 91 }else{ 92 chain.addTransit(scheduel.tranListForward.get(index)); 93 } 94 list.remove(0); 95 96 /**遍历当前剩余车次搜索到最长车次链 */ 97 int i=0; 98 while(i<list.size()) 99 { 100 int next = list.get(i); 101 int l = chain.theChain.size(); 102 /** 判断该车次是上行还是下行 */ 103 if(next >= len) 104 { 105 next -= len; 106 if(scheduel.tranListBack.get(next).getStartTime() >= chain.end){ 107 /** 车次链上前后辆车次行驶方向不同 */ 108 if(chain.theChain.get(l-1).isForward){ 109 chain.addTransit(scheduel.tranListBack.get(next)); 110 list.remove(i); 111 } 112 else 113 i++; 114 } 115 else 116 i++; 117 } 118 else{ 119 if(scheduel.tranListForward.get(next).getStartTime() >= chain.end) 120 { 121 if(!chain.theChain.get(l-1).isForward){ 122 chain.addTransit(scheduel.tranListForward.get(next)); 123 list.remove(i); 124 } 125 else 126 i++; 127 } 128 else 129 i++; 130 } 131 } 132 return chain; 133 } 134 135 /** 136 * 读取上行数据 137 * @throws IOException 138 */ 139 public static void inputForward(Scheduel scheduel) throws IOException{ 140 try{ 141 int i = 0; 142 FileInputStream fis = new FileInputStream(forward); 143 InputStreamReader isr = new InputStreamReader(fis); 144 @SuppressWarnings("resource") 145 LineNumberReader lnr = new LineNumberReader(isr); 146 String s = null; 147 while ((s = lnr.readLine()) != null) { 148 int data = Integer.parseInt(s.trim()); 149 Transit t = new Transit(); 150 t.setID(i); 151 t.setStartTime(data); 152 t.setArriveTime(data+Transit.RUN_FOWARD_TIME); 153 t.setForward(true); 154 if(i!=0) 155 t.setAdjust(scheduel.tranListForward.get(i-1)); 156 scheduel.addTransitForward(t); 157 i++; 158 } 159 }catch(FileNotFoundException e){ 160 e.printStackTrace(); 161 } 162 System.out.println("上行数据: "); 163 System.out.println(scheduel.tranListForward.size()); 164 } 165 166 /** 167 * 读取下行数据 168 * @throws IOException 169 */ 170 public static void inputBackward(Scheduel scheduel) throws IOException{ 171 try{ 172 int i = 0; 173 int len = scheduel.tranListForward.size(); 174 FileInputStream fis = new FileInputStream(backward); 175 InputStreamReader isr = new InputStreamReader(fis); 176 @SuppressWarnings("resource") 177 LineNumberReader lnr = new LineNumberReader(isr); 178 String s = null; 179 while ((s = lnr.readLine()) != null) { 180 int data = Integer.parseInt(s.trim()); 181 Transit t = new Transit(); 182 t.setID(i+len); 183 t.setStartTime(data); 184 t.setArriveTime(data+Transit.RUN_BACK_TIME); 185 t.setForward(false); 186 scheduel.addTransitBack(t); 187 if(i!=0) 188 t.setAdjust(scheduel.tranListBack.get(i-1)); 189 i++; 190 } 191 }catch(FileNotFoundException e){ 192 e.printStackTrace(); 193 } 194 System.out.println("下行数据: "); 195 System.out.println(scheduel.tranListBack.size()); 196 } 197 198 /** 199 * 根据当前时刻表,不作改动,计算固定行车计划 200 * 201 * @param scheduel 当前时刻表 202 * @return chainList 固定行车计划车次链集合 203 */ 204 public static ArrayList<TrainsitChain> creatFixedPlan(Scheduel scheduel){ 205 ArrayList<TrainsitChain> chainList = new ArrayList<TrainsitChain>(); 206 ArrayList<Integer> trainsitList = new ArrayList<Integer>(); 207 trainsitList = sortScheduel(scheduel); 208 while(!trainsitList.isEmpty()) 209 { 210 chainList.add(searchChain(trainsitList,scheduel)); 211 } 212 System.out.println("车次链数目(最小车队规模): "+chainList.size()); 213 214 int n = chainList.size(); 215 int i; 216 for( i=0;i<n;i++) 217 { 218 int m = chainList.get(i).theChain.size(); 219 System.out.println("车次链:"+ (i+1) +"的组成:"); 220 System.out.println(); 221 for(int j=0;j<m;j++) 222 { 223 System.out.print(chainList.get(i).theChain.get(j).getStartTime()+"("+chainList.get(i).theChain.get(j).getIsForward()+")"+" , "); 224 } 225 System.out.println(); 226 } 227 228 return chainList; 229 } 230 231 /** 232 * 在允许范围内调整发车时刻得到可变行车计划 233 * @param scheduel 行车计划 234 * @param plan 固定行车计划 235 * @return chain 可变行车计划 236 */ 237 public static ArrayList<TrainsitChain> creatVariablePlan(Scheduel scheduel, ArrayList<TrainsitChain> plan){ 238 sum++; 239 System.out.println("********************** 可变行车计划 *******************************"); 240 // System.out.println("********************** 原始发车时刻表 *******************************"); 241 // for(Transit t:scheduel.tranListForward) 242 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime() ); 243 // for(Transit t:scheduel.tranListBack) 244 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime() ); 245 246 ArrayList<TrainsitChain> chain; 247 248 /** 计算n值,找到最大点 */ 249 int last = scheduel.tranListForward.size(); 250 for(Transit t:scheduel.tranListForward){ 251 for(Transit s:scheduel.tranListBack){ 252 if(s.getStartTime() >= t.getArriveTime()){ 253 if(s.getArriveTime() >= scheduel.tranListForward.get(last-1).getStartTime()) 254 t.setN(scheduel.tranListForward.get(last-1).getID() - t.getID() + 1); 255 for(Transit o:scheduel.tranListForward){ 256 if(o.getStartTime() >= s.getArriveTime()){ 257 t.setN(o.getID() - t.getID()); 258 break; 259 } 260 } 261 break; 262 } 263 } 264 } 265 int size = scheduel.tranListBack.size(); 266 for(Transit t:scheduel.tranListBack){ 267 for(Transit s:scheduel.tranListForward){ 268 if(s.getStartTime() >= t.getArriveTime()){ 269 if(s.getArriveTime() >= scheduel.tranListBack.get(size-1).getStartTime()) 270 t.setN(scheduel.tranListBack.get(size-1).getID() - t.getID() + 1); 271 for(Transit o:scheduel.tranListBack){ 272 if(o.getStartTime() >= s.getArriveTime()){ 273 t.setN(o.getID() - t.getID()); 274 break; 275 } 276 } 277 break; 278 } 279 } 280 } 281 int max = 0, maxID = 0; 282 for(Transit t:scheduel.tranListForward){ 283 if(t.getN() > max){ 284 max = t.getN(); 285 maxID = t.getID(); 286 } 287 } 288 for(Transit t:scheduel.tranListBack){ 289 if(t.getN() > max){ 290 max = t.getN(); 291 maxID = t.getID(); 292 } 293 } 294 295 // System.out.println("********************** N值表 *******************************"); 296 // for(Transit t:scheduel.tranListForward) 297 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime()+ " N 值:" + t.getN() ); 298 // for(Transit t:scheduel.tranListBack) 299 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime()+ " N 值:" + t.getN() ); 300 301 // System.out.println("最大N值:" + max + " " + "最大N值点:" + maxID); 302 /** 调整发车时间 */ 303 Transit first; 304 if(maxID < scheduel.tranListForward.size()) 305 first = scheduel.tranListForward.get(maxID); 306 else 307 first = scheduel.tranListBack.get(maxID-scheduel.tranListForward.size()); 308 Scheduel s = adjustScheduel(scheduel,first); 309 //System.out.println("******************* " + s.tranListBack.get(14-s.tranListForward.size()).getArriveTime() + "*****************"); 310 311 /** 搜索车次链 */ 312 chain = creatFixedPlan(s); 313 314 /** 判断是否继续搜索 */ 315 // System.out.println(" "); 316 // System.out.println(" 可变行车计划: "); 317 // System.out.println("可变计划最小车队规模: " + chain.size()); 318 // System.out.println(" "); 319 // System.out.println("可变行车计划:"); 320 int n = chain.size(); 321 int i; 322 for( i=0;i<n;i++) 323 { 324 int m = chain.get(i).theChain.size(); 325 // System.out.println("车次链:"+ (i+1) +"的组成:"); 326 // System.out.println(); 327 for(int j=0;j<m;j++) 328 { 329 //System.out.print(chain.get(i).theChain.get(j).getStartTime()+"("+chain.get(i).theChain.get(j).getIsForward()+")"+" , "); 330 } 331 //System.out.println(); 332 } 333 334 /** 再求解一次调整之后的计算n值,找到最大点 */ 335 int last1 = scheduel.tranListForward.size(); 336 for(Transit t:scheduel.tranListForward){ 337 for(Transit s1:scheduel.tranListBack){ 338 if(s1.getStartTime() >= t.getArriveTime()){ 339 if(s1.getArriveTime() >= scheduel.tranListForward.get(last1-1).getStartTime()) 340 t.setN(scheduel.tranListForward.get(last1-1).getID() - t.getID() + 1); 341 for(Transit o:scheduel.tranListForward){ 342 if(o.getStartTime() >= s1.getArriveTime()){ 343 t.setN(o.getID() - t.getID()); 344 break; 345 } 346 } 347 break; 348 } 349 } 350 } 351 int size1 = scheduel.tranListBack.size(); 352 for(Transit t:scheduel.tranListBack){ 353 for(Transit s1:scheduel.tranListForward){ 354 if(s1.getStartTime() >= t.getArriveTime()){ 355 if(s1.getArriveTime() >= scheduel.tranListBack.get(size1-1).getStartTime()) 356 t.setN(scheduel.tranListBack.get(size1-1).getID() - t.getID() + 1); 357 for(Transit o:scheduel.tranListBack){ 358 if(o.getStartTime() >= s1.getArriveTime()){ 359 t.setN(o.getID() - t.getID()); 360 break; 361 } 362 } 363 break; 364 } 365 } 366 } 367 int max1 = 0; 368 int maxID1 = 0; 369 for(Transit t:scheduel.tranListForward){ 370 if(t.getN() > max1){ 371 max1 = t.getN(); 372 maxID1 = t.getID(); 373 } 374 } 375 for(Transit t:scheduel.tranListBack){ 376 if(t.getN() > max1){ 377 max1 = t.getN(); 378 maxID1 = t.getID(); 379 } 380 } 381 //// System.out.println("调整之后最大N:" + max1); 382 //// System.out.println("********************** 调整之后的N值表 *******************************"); 383 // for(Transit t:s.tranListForward) 384 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime()+ " N 值:" + t.getN() ); 385 // for(Transit t:s.tranListBack) 386 // System.out.println("ID: " + t.getID() + " 发车时间:" + t.getStartTime()+ " N 值:" + t.getN() ); 387 int newN = 0; 388 if(maxID >= scheduel.tranListForward.size()) 389 newN = scheduel.tranListBack.get(maxID-s.tranListForward.size()).getN(); 390 else 391 newN = scheduel.tranListForward.get(maxID).getN(); 392 System.out.println("调整之后原最大N——new:" + newN); 393 if(max1 > newN ){ 394 chain = creatVariablePlan(s,chain); 395 } 396 else{ 397 System.out.println("求解结束!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 398 } 399 return chain; 400 } 401 402 /** 403 * 允许范围内调整时刻表缩减单条线路最小车队规模 404 * 405 * @param scheduel 初始时刻表 406 * @param plan 固定行车计划 407 * @param t 开始调整的初始车次 408 * @return adj_scheduel 调整后的时刻表 409 */ 410 public static Scheduel adjustScheduel(Scheduel scheduel, Transit t){ 411 412 final int RUNTIME_FORWARD = Transit.RUN_FOWARD_TIME; 413 final int RUNTIME_BACK = Transit.RUN_BACK_TIME; 414 415 /** 获取初始车次的ID */ 416 int id = t.getID(); 417 // System.out.println("查找到的初始车次序号:" + t.getID() +"发车时间:"+ t.getStartTime()); 418 419 int a = t.getArriveTime() - t.adjust; 420 // System.out.println("初始车次的最早发车后到达末站的时刻:" + a); 421 int b = 0; 422 if(id >= scheduel.tranListForward.size()){//初始车次位于下行方向 423 // System.out.println("初始值位于上行方向,T(j-1)位于下行方向"); 424 id = id - scheduel.tranListForward.size(); 425 426 /** 寻找初始车次的第一个可行车次链上的下一个车次 */ 427 int num = 0; 428 for(Transit e: scheduel.tranListForward){ 429 if((e.getStartTime()+e.getAdjust()) >= a){ 430 // System.out.println("下一个可行车次:" + e.getArriveTime()); 431 num = e.getID(); 432 b = e.getStartTime(); 433 if(b >= a){ 434 t.setStartTime(t.getStartTime()-t.getAdjust()); 435 t.setArriveTime(t.getStartTime() + 15); 436 for(Transit o: scheduel.tranListBack){ 437 if(o.getStartTime()+o.getAdjust() >= e.getArriveTime()){ 438 if(o.getStartTime() < e.getArriveTime()){ 439 o.setStartTime(o.getStartTime()+o.getAdjust()); 440 o.setArriveTime(o.getStartTime() + 15); 441 o.adjust = 0; 442 // System.out.println("调整 ID:" + o.getID() + "的值为: " + o.getStartTime() ); 443 } 444 } 445 } 446 } 447 else{ 448 e.setStartTime(e.getStartTime()+e.getAdjust()); 449 e.setArriveTime(e.getStartTime() + 15); 450 e.adjust = 0; 451 // System.out.println("调整 ID:" + e.getID() + "的值为: " + e.getStartTime() ); 452 if(t.getArriveTime() < e.getStartTime()){ 453 t.setStartTime(t.getStartTime()-t.getAdjust()); 454 t.setArriveTime(t.getStartTime() + 15); 455 // System.out.println("调整 ID:" + t.getID() + "的值为: " + t.getStartTime() ); 456 } 457 } 458 break; 459 } 460 } 461 } 462 else{//初始车次位于上行方向 463 /** 寻找初始车次的第一个可行车次链上的下一个车次 */ 464 int num = 0; 465 for(Transit e: scheduel.tranListForward){ 466 if((e.getStartTime()+e.getAdjust()) >= a){ 467 num = e.getID(); 468 b = e.getStartTime(); 469 if(b >= a){ 470 t.setStartTime(t.getStartTime()-t.getAdjust()); 471 t.setArriveTime(t.getStartTime() + 15); 472 for(Transit o: scheduel.tranListBack){ 473 if(o.getStartTime()+o.getAdjust() >= e.getArriveTime()){ 474 if(o.getStartTime() < e.getArriveTime()){ 475 o.setStartTime(o.getStartTime()+o.getAdjust()); 476 o.setArriveTime(o.getStartTime() + 15); 477 o.adjust = 0; 478 } 479 } 480 } 481 } 482 else{ 483 e.setStartTime(e.getStartTime()+e.getAdjust()); 484 e.setArriveTime(e.getStartTime() + 15); 485 e.adjust = 0; 486 if(t.getArriveTime() < e.getStartTime()){ 487 t.setStartTime(t.getStartTime()-t.getAdjust()); 488 t.setArriveTime(t.getStartTime() + 15); 489 } 490 } 491 break; 492 } 493 } 494 } 495 return scheduel; 496 } 497 } 498 499 /** 500 * TrainsitChain类 501 * 502 * @author Karel Zuo 503 * @time 2015.6.7 504 * @version 1.0 505 * @description 该类是车次链类,一个车次链由可以被同一辆车执行的所有车次组成 506 */ 507 public class TrainsitChain { 508 509 /** 车次链上第一个车次的发车时刻 */ 510 float first = 0; 511 /** 车次链上最后一辆车到站时间 */ 512 float end = 0; 513 /** 车次链上每一个车次的集合 */ 514 ArrayList<Transit> theChain = new ArrayList<>(); 515 516 /** 517 * 添加车次到车次链 518 * @param transit 车次 519 */ 520 public void addTransit(Transit transit){ 521 if(first == 0){ 522 first = transit.startTime; 523 end = transit.arriveTime; 524 theChain.add(transit); 525 } 526 else{ 527 end = transit.arriveTime; 528 theChain.add(transit); 529 } 530 } 531 } 532 533 public class Scheduel { 534 535 /** 上行时刻表的所有车次集合 */ 536 ArrayList<Transit> tranListForward = new ArrayList<Transit>(); 537 /** 下行行时刻表的所有车次集合 */ 538 ArrayList<Transit> tranListBack = new ArrayList<Transit>(); 539 540 /** 541 * @param trainsit 车次对象 542 */ 543 public void addTransitForward(Transit tansit){ 544 this.tranListForward.add(tansit); 545 } 546 547 /** 548 * @param trainsit 车次对象 549 */ 550 public void addTransitBack(Transit tansit){ 551 this.tranListBack.add(tansit); 552 } 553 554 /** 555 * @return tranListForward 上行车次集合 556 */ 557 public List<Transit> getTranListForeard(){ 558 return this.tranListForward; 559 } 560 561 /** 562 * @return tranListBack 下行车次集合 563 */ 564 public List<Transit> getTranListBack(){ 565 return this.tranListBack; 566 } 567 } 568 569 /** 570 * 车次类 571 * 572 * @author Karel Zuo 573 * @time 2015.6.4 574 * @version 1.0 575 * @description 该类用于表示一个车次的全部信息 576 */ 577 public class Transit { 578 /** 上行方向运行时间 */ 579 public final static int RUN_FOWARD_TIME = 59;//65; 580 /** 下行方向运行时间 */ 581 public final static int RUN_BACK_TIME = 62;//58; 582 /** 车辆运行方向 */ 583 boolean isForward; 584 /** 发车时间 */ 585 int startTime; 586 /** 到站时间 */ 587 int arriveTime; 588 /** 车次ID */ 589 int id; 590 /** 发车时间允许调整范围 */ 591 int adjust = 0; 592 /** 车次的n值 */ 593 int N = 0; 594 595 /** 596 * @return startTime 发车时间 597 */ 598 public int getStartTime(){ 599 return this.startTime; 600 } 601 602 /** 603 * @return arriveTime 到站时间 604 */ 605 public int getArriveTime(){ 606 return this.arriveTime; 607 } 608 609 /** 610 * @return id 车次id 611 */ 612 public int getID(){ 613 return this.id; 614 } 615 616 /** 617 * @return isForward 车辆运行方向 618 */ 619 public boolean getIsForward(){ 620 return this.isForward; 621 } 622 623 /** 624 * @param adjust 发车时刻允许调整范围 625 */ 626 public int getAdjust(){ 627 return this.adjust; 628 } 629 630 /** 631 * @param N 该车次的N值 632 */ 633 public int getN(){ 634 return this.N; 635 } 636 637 /** 638 * @param time 设置的发车时间 639 */ 640 public void setStartTime(int time){ 641 this.startTime = time; 642 } 643 644 /** 645 * @param time 设置的到站时间 646 */ 647 public void setArriveTime(int time){ 648 this.arriveTime = time; 649 } 650 651 /** 652 * @param id 车次序号 653 */ 654 public void setID(int id){ 655 this.id = id; 656 } 657 658 /** 659 * @param isForward 车次运行方向 660 */ 661 public void setForward(boolean isForward){ 662 this.isForward = isForward; 663 } 664 665 /** 666 * @param t 车次链上相连的前一个车次 667 */ 668 public void setAdjust(Transit t){ 669 int adjust = 0;//this.startTime - t.getStartTime(); 670 if(adjust < 10) 671 adjust = (int)(0.7*adjust); 672 else if(adjust < 20) 673 adjust = (int)(0.5*adjust); 674 else if(adjust < 40) 675 adjust = (int)(0.4*adjust); 676 else 677 adjust = (int)(0.3*adjust); 678 this.adjust = adjust; 679 } 680 681 /** 682 * @param time 设置的发车时间 683 */ 684 public void setN(int N){ 685 this.N = N; 686 } 687 }
---恢复内容结束---
时间: 2024-10-12 12:13:14