题意:给定一个数列,要求把数列切分成m个段,使得总和最大的一段的总和最小。求这个总和。
分析:只知道dp的方法,但是超时。后来知道是二分。就是二分查找一个阶段消费的上限(总和)。每次可以用O(n)的效率来判断这个值是不是符合。我们要找的就是符合条件的最小值。
View Code
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 100005
int n, m, f[maxn], l, r, mid;
void init()
{
scanf("%d%d", &n, &m);
l =0;
r =0;
for (int i =0; i < n; i++)
{
scanf("%d", &f[i]);
if (l < f[i])
l = f[i];
r += f[i];
}
}
bool ok(int a)
{
int sum =0, j =0;
for (int i =0; i < n; i++)
{
if (sum + f[i] > a)
{
sum = f[i];
j++;
}
else
sum += f[i];
}
j++;
if (j > m)
returnfalse;
returntrue;
}
void binarysearch()
{
while (l < r)
{
mid = (l + r) /2;
if (!ok(mid))
l = mid +1;
else
r = mid;
}
printf("%d\n", l);
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
init();
binarysearch();
return0;
}
#include <iostream>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 100005
int n, m, f[maxn], l, r, mid;
void init()
{
scanf("%d%d", &n, &m);
l =0;
r =0;
for (int i =0; i < n; i++)
{
scanf("%d", &f[i]);
if (l < f[i])
l = f[i];
r += f[i];
}
}
bool ok(int a)
{
int sum =0, j =0;
for (int i =0; i < n; i++)
{
if (sum + f[i] > a)
{
sum = f[i];
j++;
}
else
sum += f[i];
}
j++;
if (j > m)
returnfalse;
returntrue;
}
void binarysearch()
{
while (l < r)
{
mid = (l + r) /2;
if (!ok(mid))
l = mid +1;
else
r = mid;
}
printf("%d\n", l);
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
init();
binarysearch();
return0;
}