---
# System prepended metadata

title: 【UVA】907.Winterim Backpacking Trip

---

# 【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;
}
```