第七章 分治算法-1243:月度開銷

1243:月度開銷

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 5287 通過數: 1850
【題目描述】
農夫約翰是一個精明的會計師。他意識到自己可能沒有足夠的錢來維持農場的運轉了。他計算出並記錄下了接下來 N (1 ≤ N ≤ 100,000) 天裏每天需要的開銷。

約翰打算爲連續的M (1 ≤ M ≤ N) 個財政週期創建預算案,他把一個財政週期命名爲fajo月。每個fajo月包含一天或連續的多天,每天被恰好包含在一個fajo月裏。

約翰的目標是合理安排每個fajo月包含的天數,使得開銷最多的fajo月的開銷儘可能少。

【輸入】
第一行包含兩個整數N,M,用單個空格隔開。

接下來N行,每行包含一個1到10000之間的整數,按順序給出接下來N天裏每天的開銷。

【輸出】
一個整數,即最大月度開銷的最小值。

【輸入樣例】
7 5
100
400
300
100
500
101
400
【輸出樣例】
500
【提示】
若約翰將前兩天作爲一個月,第三、四兩天作爲一個月,最後三天作爲一個月,則最大月度開銷爲500。其他任何分配方案都會比這個值更大。


思路:分治用二分來做。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,a[100009], maxx = 0, tot,ans;

bool check(int);
int main(){
	scanf("%d%d",&n,&m);//輸入n天,m個財政週期
	for(int i = 1; i <= n ;i++)
	{
		scanf("%d",&a[i]);
		tot += a[i];//二分的右端點是總的開銷 
		if(a[i] > maxx ) maxx = a[i];//二分的左端點是n天中最大的開銷 
	}
	int l = maxx, r = tot, mid;
	while(l <= r)
	{
		mid = (l + r)>>1;
		if(check(mid)){
			ans = mid;//記錄答案 
			r = mid -1;
			
		}
		else
		l = mid + 1;//否則擴大範圍 
	}
	printf("%d" ,ans);
	
}
bool check(int x){//當最小值是x時是否可以 
	int sum = 0, month = 1;
	for(int i = 1; i<=n; i++)
	{
		if(sum + a[i] > x)//sum是一直累加,當超過x時月份++,說明這一天自己另一個月份 
		{
			sum = a[i];
			month++;
			
		}else
	      sum += a[i];
	
	}
	if(month <= m) return 1;//月份等於m時正好分成m個月份,小於m時,可以將某些月份中的天數拆開組成新月份,滿足分成m個月份 
	else
	 return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章