poj 3273"Monthly Expense"(二分搜索+最小化最大值)

传送门

https://www.cnblogs.com/violet-acmer/p/9793209.html

题意:

  有 N 天,第 i 天会有 a[ i ] 的花费;

  将这 N 天分成 M 份,每份包含 1 天或连续的多天;

  每份的花费为包含的天数花费的加和,求最大花费的最小值。

题解:

  二分搜索答案。

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn=1e5+10;
 5 
 6 int N,M;
 7 int totMoney;
 8 int a[maxn];
 9 
10 bool Check(int mid)
11 {
12     int res=0;
13     int curSum=0;
14     for(int i=1;i <= N;++i)
15     {
16         if(a[i] > mid)
17             return false;
18         if(curSum+a[i] > mid)
19         {
20             res++;
21             curSum=a[i];
22         }
23         else
24             curSum += a[i];
25     }
26     res++;//一定要 ++,for()当i == N 时,不会计算在res中
27     return res <= M ? true:false;
28 }
29 int Solve()
30 {
31     int l=0,r=totMoney+1;
32     while(r-l > 1)
33     {
34         int mid=l+((r-l)>>1);
35         if(Check(mid))
36             r=mid;
37         else
38             l=mid;
39     }
40     return r;
41 }
42 int main()
43 {
44 //    freopen("C:\Users\lenovo\Desktop\in.txt\poj3273.txt","r",stdin);
45     scanf("%d%d",&N,&M);
46     totMoney=0;
47     for(int i=1;i <= N;++i)
48     {
49         scanf("%d",a+i);
50         totMoney += a[i];
51     }
52     printf("%d
",Solve());
53     return 0;
54 }
View Code

  坑:

  (1) : Check()中for( )后res为++

  (2) : 题干中给的“the exact amount of money (1 ≤ moneyi ≤ 10,000)”貌似没啥用,需要自己判断二分的右边界

原文地址:https://www.cnblogs.com/violet-acmer/p/10167754.html