POJ3273-Monthly Expense
题意:
给你n天的预期,你需要把这n天划分成m段(保证原序列位置不变),让你使这m段中的最大值尽可能小,你要怎么划分。
题解:
1 //题解: 2 //题目很明显就是一道二分题。你要去二分答案。 3 #include<stdio.h> 4 #include<stdlib.h> 5 #include<iostream> 6 #include<string.h> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=500005; 10 const int INF=0x3f3f3f3f; 11 typedef long long ll; 12 int v[maxn],n,m,w[maxn]; 13 int panduan(int x) //我的判断方法就是截取法,首先从0号位置开始看最大能截取到那个位置,然后再从新位置在开始 14 { //截取 15 int ans=1; 16 for(int i=1;i<=n;++i) 17 { 18 if(v[i]>x) return 0; 19 if(w[i-1]+v[i]<=x) w[i]=w[i-1]+v[i]; 20 else w[i]=v[i],ans++; 21 } 22 if(ans<=m) return 1; //截取的次数小于m的话就可以。为什么可以自己想一想 23 else return 0; 24 } 25 int main() 26 { 27 while(~scanf("%d%d",&n,&m)) 28 { 29 memset(v,0,sizeof(v)); 30 memset(w,0,sizeof(w)); 31 int r=0; 32 for(int i=1; i<=n; ++i) 33 scanf("%d",&v[i]),r+=v[i]; 34 int l=0,mid,ans=r/2; //我一直很疑惑这里的ans要初始化为r/2,不初始化的话就会报错。。。 35 while(l<=r) 36 { 37 mid=(l+r)>>1; 38 if(!panduan(mid)) 39 { 40 l=mid+1; 41 } 42 else 43 { 44 ans=mid; 45 r=mid-1; 46 } 47 } 48 printf("%d\n",ans); 49 } 50 return 0; 51 }