poj 2336 ferry loadII


/*
* 通过渡船运输车辆过河
* m辆车辆按照一定时间次序到原岸边
* 只有一个渡船,可以运输n量车,运输到对岸需要时间t
* 回到原岸需要时间t
* 问最少需要多少时间可以将车辆全部运到对岸
* 在时间最短的情况下,最少需要运输几次
*
*
Sample Input
//2个test case,渡船一次可载2辆车,单程运输需要10分钟,
//有10辆车需要运输,分别在0,10,20..时刻到原岸
//test case num
//n t m
//arriving time of car 0
//...
//arriving time of car m - 1
2
2 10 10
0
10
20
30
40
50
60
70
80
90
2 10 3
10
30
40
Sample Output
100 5
50 2
思路,贪心
最早运到对岸的时间,取决与最后来的一辆车的被运送时间。因此最优解即是最后一辆车能够最早
被运送。
假设有12辆车,渡船一次可以载5辆车,则问题可转换为前面7辆车的最早运送并且船只回来的时间
和最后一辆车的到达原岸时间中的晚者作为最后5辆车的最后出发时间。
如此对于前面7辆车是同样的问题,规模缩小。
所以问题解法是如果m%n == 0,则每次都运送n辆车,否则第一次运输m%n辆,以后每次都运送n辆车,
每次都运送到达时间上连续的一组车。
这种解法同时也是能够运送船只最少次数(m/n上取整)的解法,不可能运送更少的次数了。

#include <iostream>
using namespace std;
int n, t, m;
void SolveGreedy() 
{
      int l = m % n;
      int k = m / n;
      int time_now;   //当前船只来到原岸的时间
      int time_return = 0; //前一组运送渡船的返回时间
      int trans_times = k;
      if (l) {
           trans_times += 1;
            for (int i = 0; i < l; i++)
            cin >> time_now;
            time_return = time_now + 2 * t;
       }
      for (int i = 0; i < k; i++) {
           for (int j = 0; j < n; j++)
                  cin >> time_now;
            if (time_now <= time_return)
                  time_return = time_return + 2 * t;
            else
                  time_return = time_now + 2 * t;
       }
      //输出结果
      cout << time_return - t <<" " << trans_times << endl;
}
int main(int argc, char *argv[])
{
      int testNum;
      cin >> testNum;
      while (testNum--) {
           cin >> n >> t >> m;
            SolveGreedy();
      }
     return 0;
}
原文地址:https://www.cnblogs.com/rocketfan/p/1522213.html