http://poj.org/problem?id=3273
无数WA,参照AC代码才发现
最后一天的cnt++的判定错了,要放在if外面
int check(int sub)
{
int sum=0,k=0,i;
for(i=0;i<N;i++)
{
sum+=a[i];
if(sum>sub)
{
k++;
sum=a[i];
}
}
if(sum!=0) k++;
return k<=M;
}
另一种上下界判定的二分搜索:
//在其他的题目中:使用(low+high)/2可能会有整数溢出的问题
//(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
//这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题
void solve1(int a, int b)
{
int l = a, r = b;
int res = 0;
while(l <= r)
{
int mid = l + (r-l)/2;
if(C(mid))
{
r = mid - 1;
res = mid;
}
else
l = mid + 1;
}
printf("%d\n", res);
}
#include <iostream>
#include <cstdio>
using namespace std;
const int MAX_N = 1e5, INF = 1e4 * MAX_N+1;
int L, N, M;
int a[MAX_N+10];
bool C(int x)
{
int cnt = 0, sum = 0;
for(int i = 0; i < N; i++)
{
if(sum + a[i] > x) //总和超过预算
{
if(a[i] > x) return false; //变大
sum = a[i];
cnt++;
if(cnt > M)
return false; //变大
}
else
{
sum += a[i];
}
}
if(sum > 0)
cnt++; //有剩余
if(cnt <= M)
return true; //变小
else
return false; //变大
}
void solve1(int a, int b)
{
int l = a, r = b;
int res = 0;
while(l <= r)
{
int mid = l + (r-l)/2;
if(C(mid))
{
r = mid - 1;
res = mid;
}
else
l = mid + 1;
}
printf("%d\n", res);
}
void solve(int a, int b)
{
int l = a-1, r = b;
while(r - l > 1)
{
int mid = (l + r) / 2;
if(C(mid))
r = mid; //符合条件,尝试更小
else
l = mid; //不符合条件,变大
}
printf("%d\n", r);
}
int main()
{
//freopen("in.txt", "r", stdin);
scanf("%d%d", &N, &M);
int Max = -1, sum = 0;
for(int i = 0; i < N; i++)
{
scanf("%d", a+i);
Max = max(Max, a[i]);
sum += a[i];
}
solve(Max, sum);
return 0;
}