# 【UVA】907.Winterim Backpacking Trip ## [907.Winterim Backpacking Trip](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=848>) ## 時間複雜度 * $O(<N*log(D)>)$ ## 解題想法 這題很難,我覺得是很難理解 題目給你總共有N個露營區,以及K個晚上,接下來的側資是每個露營區的距離。 舉個例子: 假設,N=4、K=3、{7,2,6,4,8}代表每個露營區的距離,大概的路徑就是O(原點)-->7-->2-->6-->4-->8-->END,露營區的位置是固定的,所以你必須走到露營區才能休息,總不可能停在半路上,所以我們需要找出一個平衡點->在K個晚上可以走完,也不會超過自身負擔的走路距離。 ※目標:時間內走完,不會太有負擔, Approach: 這題可以透過二分搜(Binary Search)直接解,但還要注意**能不能走完跟會不會超過限制天數**,上下界很好理解,下界就是這幾段的最大距離,如果不是最大距離,你再怎麼走都走不完,因為走不夠遠,到不了下個露營區,而上界就是全部的距離,以極端情況來說,你一天就走完全程。 接下來是判斷部分,你可以想成模擬登山,這個距離我開始走,能不能走完,會不會造成很大負擔,進而用bool true/false表達,如果可以的話,確認能不能同一天再走更少一點,這樣就能更輕鬆地達成;如果不行,那我是不是可以每天走更多一點,這樣也許在時間內能走完。 ## 完整程式 <你的程式> ```cpp= #include<iostream> #include<vector> #include<algorithm> using namespace std; using ll = long long; bool check(ll mid,ll nights,vector<ll> dis){ ll count=0,nights_spend=0,i=0; for(int x=0;x<dis.size();x++){ if(dis[x]>mid)return false; if(count+dis[x]>mid){ nights_spend++; count=dis[x]; } else{ count+=dis[x]; } } if(nights_spend>nights)return false; else return true; } int mid_dis(vector<ll> dis,ll nights){ ll largest=0,least=*max_element(dis.begin(),dis.end()); for(auto&c:dis)largest+=c; ll nights_spend=0,current_distance=0,ans; while(least<=largest){ ll mid = least + (largest-least)/2; if(check(mid,nights,dis)){ largest = mid-1; ans=mid; } else{ least = mid+1; } } return ans; } int main(){ ll campsites,nights,input; while(cin>>campsites>>nights){ vector<ll> dis; for(ll i=0;i<=campsites;i++){cin>>input;dis.push_back(input);} cout<<mid_dis(dis,nights)<<endl; } return 0; } ```