POJ_3273_Monthly_Expense_(二分,最小化最大值)

描述


http://poj.org/problem?id=3273

共n个月,给出每个月的开销.将n个月划分成m个时间段,求m个时间段中开销最大的时间段的最小开销值.

Monthly Expense
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 21446   Accepted: 8429

Description

Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.

FJ wants to create a budget for a sequential set of exactly M (1 ≤ MN) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.

FJ's goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.

Input

Line 1: Two space-separated integers: N and M
Lines 2..N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day

Output

Line 1: The smallest possible monthly limit Farmer John can afford to live with.

Sample Input

7 5
100
400
300
100
500
101
400

Sample Output

500

Hint

If Farmer John schedules the months so that the first two days are a month, the third and fourth are a month, and the last three are their own months, he spends at most $500 in any month. Any other method of scheduling gives a larger minimum monthly limit.

Source

分析


二分.

最小化最大值.

和"河中跳房子","Agressive Cows"等最大化最小值问题正好相反的最小化最大值问题,同样用二分解决,原理基本相同,差别主要在C条件的判断上.

1.最大化最小值:

相当于n个东西分给m个人,使得每个人至少拿x个,那么每个人拿够了就走,给后面的人多留一点,只要能分够>=m个人就是true,多的全扔给最后一个人就是了.

2.最小化最大值:

相当于n个东西分给m个人,每个人至多能拿x个,那么每个人尽可能多拿一点,给后面的人少留一点,只要能使<=m个人分完这n个东西就是true,之后每个人随便拿一点给没有拿到的人就是了.

 

注意:

1.如上所述两种问题的区别.

2.关于初始值.有些题直接给前缀和(如之前提到的两题),那样最小值的最大值就是平均值,最大值的最小值也是平均值,但像这道题,如果算sum可能会炸,而且不知道会炸到啥程度,所以不能瞎搞,只能乖乖设定y为0x7fffffff,x为单点最大值.

对于可以计算sum的题有:

<1>.最大化最小值:

x为单点最小值,y为平均值.

<2>.最小化最大值:

x为平均值与单点最大值两者中大的那一个,y为sum.其实直接令x=0,y=0x7fffffff即可,不过循环32次而已...

 

p.s.看懂别人的代码不重要,重要的是要理解算法的思想,不同的代码只是实现算法的方式不同与个人喜好问题而已,要真正想明白,把东西转化成自己的.

 1 #include<cstdio>
 2 #include<algorithm>
 3 using std :: max;
 4 
 5 const int maxn=100005;
 6 int n,m,maxa=0;
 7 int a[maxn];
 8 
 9 void init()
10 {
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)
13     {
14         scanf("%d",&a[i]);
15         maxa=max(maxa,a[i]);
16     }
17 }
18 
19 bool C(int x)
20 {
21     int sum=0,ans=1;
22     for(int i=1;i<=n;i++)
23     {
24         sum+=a[i];
25         if(sum>x)
26         {
27             sum=a[i];
28             ans++;
29         }
30     }
31     if(ans<=m) return true;
32     return false;
33 }
34 
35 void solve()
36 {
37     int x=maxa,y=0x7fffffff;
38     while(x<y)
39     {
40         int m=x+(y-x)/2;
41         if(C(m)) y=m;
42         else x=m+1;
43     }
44     printf("%d
",x);
45 }
46 
47 int main()
48 {
49     freopen("monthly.in","r",stdin);
50     freopen("monthly.out","w",stdout);
51     init();
52     solve();
53     fclose(stdin);
54     fclose(stdout);
55     return 0;
56 }
View Code

 

原文地址:https://www.cnblogs.com/Sunnie69/p/5423817.html