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\n",Solve()); 53 return 0; 54 }
坑:
(1) : Check()中for( )后res为++
(2) : 题干中给的“the exact amount of money (1 ≤ moneyi ≤ 10,000)”貌似没啥用,需要自己判断二分的右边界