最大值最小化
1 //目标学会用猜数字(二分)的方法,换个角度来解决问题 2 #include<stdio.h> 3 #include<string.h> 4 #include<stdlib.h> 5 const int N = 100000; 6 7 int a[N],n,m,max; 8 9 void input() 10 { 11 scanf("%d%d",&n,&m); 12 max=0; 13 for(int i=0;i<n;i++) 14 { 15 scanf("%d",&a[i]); 16 max >?= a[i]; 17 } 18 } 19 20 bool is_part(int x)//是否能把序列划分为每个序列之和不大于x的m个子序列 21 { 22 //每次往右划分,划分完后,所用的划分线不大于m-1个即可 23 int t=0,s=0; 24 bool ok=true; 25 26 for(int i=0;i<n;i++) 27 { 28 /* 29 假如有其中一个元素大于x,则极端地把划分线分别设在在其左边和右边, 30 都不能使这一个只有一个元素的序列之和不大于x,更不用说所有序列之和不大于x 31 */ 32 if(a[i]>x) 33 { 34 ok=false; 35 break; 36 } 37 if(s+a[i]>x)//大于,不能再把当前元素加上了 38 { 39 t++;//多用了一条横杠 40 s=a[i]; 41 /* 42 t=m时退出,即在最后一个元素之前都已经用了m条划分线,此时已把序列划分成了m+1个序列,太过分了,让其适可而止 43 */ 44 if(t>m-1) 45 { 46 ok=false; 47 break; 48 } 49 }else 50 { 51 s+=a[i];//把当前元素与前面的元素连上,以便尽量往右划分,贪心到底 52 } 53 } 54 55 return ok; 56 } 57 58 int sum() 59 { 60 int s=0; 61 for(int i=0;i<n;i++) s+=a[i]; 62 return s; 63 } 64 65 int binary_solve() 66 { 67 int x=max,y=sum(); 68 while(x<y) 69 { 70 //求上界 71 int m=x+(y-x)/2; 72 if(is_part(m)) 73 y=m; 74 else 75 x=m+1; 76 } 77 return x; 78 } 79 80 int main() 81 { 82 input(); 83 int ans=binary_solve(); 84 printf("%d\n",ans); 85 return 0; 86 } 87 /* 88 6 3 89 1 2 3 2 5 4 90 */
此为转载……貌似是个高中生写的,太牛了……
作者:火星十一郎
本文版权归作者火星十一郎所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.