題目鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1093
題意:中文題誒~
思路:xjb
一開始死活想不出怎麼將一個中間點兩個中間點的情況推廣到多個中間點的情況,然後看了下討論,迷迷糊糊就過了..
下面一段話轉自討論:
路程是这么分的:最后一段肯定是K,且恰好携带K根香蕉
假设 N = a + K,那么剩下的问题就变成怎么从起点0运送K根香蕉到a点了,在a比较小的时候,应该只需要一个补给点,0 ---> a ----> K + a,假设从0到a往返次数为n, 则前向运输的次数为(n + 1)次,返回次数为n次,路途中消耗的香蕉为(2 * n+1) * a,因为骆驼每次运输量至多为K,
则需要满足:
K + (2 * n + 1) * a <= (n + 1) * K
取n = 1,得到 a <= K / 3。这时候,可以反过来证明在 K < N <= K + K / 3的时候,最佳的运输方案是设置一个补给点a,且从0到a 往返一次。
依此类推,N = b + K + K / 3的时候(b较小)设置两个补给点,越后面的路段越长,且往返次数越小。
...
事實上這段話也只是分析了一下1個中間點的情況,不過讓我發現了自己一開始的問題:我沒有給n定值,所以也就不能確定a的值.嘗試給a定值後,可以發現從終點到起點每兩個站點間經過的次數是有規律的,
滿足數列:1, 3, 5, 7, 9....
再注意一下最後的計算結果需要向上取整即可...
代碼:
1 #include <iostream> 2 #include <math.h> 3 using namespace std; 4 5 int main(void){ 6 int n, k, cnt=1; 7 double ans, len; 8 cin >> n >> k; 9 if(k>=n){ 10 cout << n << endl; 11 return 0; 12 } 13 ans=len=k; 14 while(n>len){ 15 cnt+=2; 16 int cc=(cnt-1)>>1; 17 double x=((cc+1)*k-ans)/(2*cc+1); 18 if(len+x>=n){ 19 double gg=n-len; 20 ans+=gg*cnt; 21 len=n; 22 }else{ 23 len+=x; 24 ans+=cnt*x; 25 } 26 } 27 cout << (int)ceil(ans) << endl;//ceil要轉int輸出,不然會輸出1e..這樣的格式..坑// 28 return 0; 29 }