ccsu 1493 青蛙过河
Description
有一条宽度为L(1≤L≤ 1,000,000)的河。河中间有N(0≤N≤20000)块石头,青蛙从河西岸经过这N个石块后,顺利跳到了河的东岸。设河中间每个石块距离西岸的距离为Di(其中Di大于0小于L)。注意:Di是距离起始河岸的距离。
小明闲着没事,想移掉河中间的M(0≤M≤N)个石块,让一些石块之间的距离增大一点,好叫青蛙没那么容易跳到对岸。
由于移除M个石块的方法有多种,所以在移除石块之前,小明想知道如果他恰好移除河中M个石块后,青蛙跳的最短距离的最大值可以达到是多少?(青蛙跳一段的距离:西岸与河中第一个石块距离、河中相邻石块的距离、最后一个石块与东岸的距离。青蛙每次都是从一个石块跳到与它相邻的下一个石块)。
Input
多组输入。第一行顺序输入L, N和M。接下来输入N个正整数(不保证有序),表示N个石块距离起始河岸的距离。
Output
对于组输入,输出移除M个石块后,整个跳跃过程中最短距离的最大值。
Sample Input
25 5 2
2
14
11
21
17
Sample Output
4
Hint
在移除石块之前,跳跃过程中的最小间距2(起点距第1个石块)。移除距离起始岸为2和14的石块后,最小间距就为4了。(0 – 11 – 17 – 21 – 25 )。
Source
poj3258
#include
#include
using namespace std;
const int size = 50002;
int D[size],L,N,M;
int minl,maxl, ans;
bool Ok(int x)
{
int tot = 0,i = 0, t = 0;
while (i<=N)
{
tot = D[i++];
while (i <= N && tot < x)
{//不能小于x, tot小于枚举的x,必须合并
tot += D[i++];
t++;//拿掉一块石头,合并一次
}
if (t > M) return 0;//要使用t次才能满足答案为x的条件,超过了M,不符合等于M的条件,返回0
}
//加上,这一句
//此时tot是最后几块合并的值,如果他小于枚举的答案x
//且t==M(也就是你之前把可以拿去M块石头的机会都用光了),
//这种情况tot为最小值,所以x不符合条件
if (tot < x && M == t) return 0;
return 1;
}
void Binary()
{
int l = minl, r = maxl, m;
while (l <= r)
{
m = (l+r)/2;//
if (Ok(m)) l = m + 1, ans = m;/*继续枚举更大的答案(最小值最大,
能够越大尽量越大),并且记录当前可行的答案 */
else r = m - 1;//枚举更小的答案
}
}
int main()
{
int i, j, k;
//freopen("B.in","r",stdin);
//freopen("tmp.out","w",stdout);
while (scanf("%d%d%d",&L,&N,&M)!=EOF)
{
for (i = 0; i < N; i++)
scanf("%d",&D[i]);
sort(D,D+N);//排序,计算石头之间的间距
D[N] = L;//最后块(也就是对岸)距离起点的距离为L
minl = maxl = ans = D[0];
for (i = N; i > 0; i--)
{
D[i] = D[i]-D[i-1];//求石头间距
//printf("%d ",D[i]);
//if (D[i] == 0) printf("AAA\n");
if (D[i]
Description
给定长度为N的序列A,其中1≤N≤100000,1≤A[i] ≤100000。现在要将A分成M段(1≤M≤N),每段有A中的1个或相邻的多个元素构成。例如A={1,3,4,6,7,8}分成3段的一种情况为B={1,(3,4),(6,7,8)}。
由于将A分成M段的情况有多种,现在要求最大子段和最小的情况。例如上述中B的子段和分别为{1,7,21}.
Input
每组输入的第一行为N和M,然后N行是序列A,为N个正整数。
Output
输出一个整数,占一行。求最小的情况下的最大子段和。
Sample Input
7 5
100
400
300
100
500
101
400
Sample Output
500
Hint
Sample中的分法为:100+400, 300+100, 500, 101, 400. 其中最大子段和为500,且此种情况为多种情况下最小的。
#include
#include
#define size 100010
using namespace std;
int n,m;
int a[size];
int ok(int x)
{
int sum = 0 , t = 0 , i = 0 , flag = 0 ,len;
while (i < n)
{
sum = a[i++];
int j=i;
while (j < n && sum < x )
{
sum+=a[j++];
}
t++;
if(sum == x) {flag =1; len = j - i + 1; }
else if( sum > x ) {j --; sum-=a[j];}
if( t > m ) return -1;
i=j;
}
if(flag == 1 && n - len >= m -1 ) return 1;
if(flag == 1 && t <= m) return 1;
return 0;
}
int find_ans(int low , int heigh)
{
int ans = 0 , mid;
while ( low <= heigh)
{
mid = (low + heigh)/2;
int temp = ok(mid);
if(temp == -1){ low = mid +1 ;}
else if(temp ) {heigh = mid - 1; ans = mid;}
else heigh = mid -1 ;
}
return ans;
}
int main()
{
int min,max;
while (scanf("%d%d",&n,&m)!=EOF)
{
min = max = 0;
for(int i=0;i min) min = a[i];
max+=a[i];
}
printf("%d\n",find_ans(min,max));
}
return 0;
}