SDUT 2778 小明的花費預算
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description
小明終於找到一份工作了,但是老闆是個比較奇怪的人,他並不是按照每月每月的這樣發工資,他覺得你想什麼時候來取都可以,而小明恰好是一個花錢比較大手大腳的人,所以他希望每次取得錢正好夠接下來的n個月的花費,以防浪費。
小明很懶,懶到他連錢都儘量不願多帶(只是嫌沉)。但是他在只有m次取錢的機會,所以他想要用m次把n個月的錢都取出來,但想要每次都儘量少取些。給你小明n個月的花費,還有可取的次數m,問小明在保證每次儘量少取些錢的情況下,最多的那次取了多少錢?當然,每次取錢只能取連續幾個月的花費。
Input
多組輸入。
第一行是兩個整數,n(1 ≤ n ≤ 100,000)和m (1 ≤ m ≤ n)
接下來的n行是連續n個月的花費,第i+1行是第i個月的花費。
Output
輸出滿足最大的總花費最小的那個組的總花費。
Example Input
5 3
3
2
9
4
1
Example Output
9
Hint
將5個月分爲3組,第一組(3,2),第二組(9),第三組(4,1),第二組的總花費最大爲9,若按其他的方式分,花費最大的那一組的總花費將>=9.
Author
lwn
Submit(帶註釋版)
#include <bits/stdc++.h>
using namespace std;
int N, M;
int n[100005];
int ans;
void binsearch(int low, int high)
{
if(low > high)//從low到high,情況越來越不理想,所以必須low <= high,當low > high的時候說明最佳答案ans已求出
return;
int mid, count = 1, i, sum = 0;//count代表取錢次數,sum代表每次取得錢數
mid = (high-low) / 2 + low;//二分,設一個low和high的中值mid,代表每次允許取的最大錢數
for(i = 0; i < N; i++)//求出若每次取得錢數不超過中值mid的條件下需要取幾次
{
if(sum + n[i] <= mid)//再繼續取1月的花費不會超過mid
sum += n[i];//sum代表某一次取的錢數
else
{
count++;//不能繼續再取錢了,要再取一次
sum = n[i];
}
}
if(count > M)//需要取的次數大於允許取得次數,說明每次允許取的錢數太小了,就確定答案範圍一定在mid到high之間
binsearch(mid+1, high);
else
{
ans = mid;
binsearch(low, mid-1);//反之就減小每次允許取得錢數
}
}
int main()
{
int low, high;//low和high是總花費最小的那個組的總花費的範圍
while(~scanf("%d %d", &N, &M))
{
low = high = 0;//總花費最小的最理想情況就是,花費最大的那個月單獨取1次,其他任意次取的錢數合都比這個月小,此處設low是這個最理想情況的花費。最不理想情況則是隻取一次,一次取出所有的花費,此處設low是這個最不理想情況
for(int i = 0; i < N; i++)
{
scanf("%d", &n[i]);
if(n[i] > low)
low = n[i];//最理想情況
high += n[i];//最大花費就是隻取一次全取完
}
binsearch(low, high);//二分的在這個範圍內精確答案
printf("%d\n", ans);
}
return 0;
}
Submit(純代碼版)
#include <bits/stdc++.h>
using namespace std;
int N, M;
int n[100005];
int ans;
void binsearch(int low, int high)
{
if(low > high)
return;
int mid, count = 1, i, sum = 0;
mid = (high-low) / 2 + low;
for(i = 0; i < N; i++)
{
if(sum + n[i] <= mid)
sum += n[i];
else
{
count++;
sum = n[i];
}
}
if(count > M)
binsearch(mid+1, high);
else
{
ans = mid;
binsearch(low, mid-1);
}
}
int main()
{
int low, high;
while(~scanf("%d %d", &N, &M))
{
low = high = 0;
for(int i = 0; i < N; i++)
{
scanf("%d", &n[i]);
if(n[i] > low)
low = n[i];
high += n[i];
}
binsearch(low, high);
printf("%d\n", ans);
}
return 0;
}