题意:
有n+1个数,让你把连续一些数组合成k+1个数,并使得组合出来的数的最大值尽量的小。
(*有一题姊妹题 lighoj 1076)
思路:
一般求最大值中的最小值问题,大多是二分。二分总长,使其满足条件后尽量小。
二分出答案后,还要输出方案(若有多种方案则使前面的值尽量大)。
输出方案一直不知道怎么处理,后来查看了下别人的思路。因为是尽量使前面的值大,所以前面的值尽量多组合在一起(在不超过二分出来的答案的情况下),组合的次数最多为n-k次。
AC代码:(写的比较挫= =)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e3+5;
const int INF = 0x3f3f3f3f;
int sum[MAXN];
int n, k;
bool OK(int mid)
{
int cot = 0;
for(int i = 1;i <= n+1; i++)
if(sum[i] - sum[i-1] > mid) return false;
//
for(int i = 1, j = 0;i <= n+1; i++)
{
if(sum[i] - sum[j] == mid || (i == n+1 && sum[i]-sum[j] <= mid) || (i != n+1 && sum[i+1] - sum[j] > mid))
{
if(i != n+1) cot++;
j = i;
}
}
if(cot <= k) return true;
else return false;
}
void findThePath(int ans)
{
int cot = n-k, i = 1;
while(i <= n+1)
{
int j = i-1;
int tsum = sum[i] - sum[i-1];
i++;
if(cot != 0)
for(;i <= n+1; i++)
{
if(sum[i] - sum[j] <= ans)
tsum = sum[i] - sum[j], cot--;
else
{
printf("%d\n", tsum);
break;
}
if(cot == 0)
{
printf("%d\n", tsum);
i++;
break;
}
}
else
printf("%d\n", tsum);
}
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &k);
int tmp, tsum = 0;
sum[0] = 0;
for(int i = 1;i <= n+1; i++)
{
scanf("%d", &tmp);
tsum += tmp;
sum[i] = sum[i-1] + tmp;
}
//
int l = 0, r = tsum;
int ans;
while(l <= r)
{
int mid = (l+r)/2;
if(OK(mid))
{
ans = mid;
r = mid-1;
}
else
l = mid+1;
}
printf("Case %d: %d\n", ++cas, ans);
findThePath(ans);
}
return 0;
}