3273:
题意:给出n个数,要求把这n个数顺序不变的分成m组(即每组数必然是连续的)。要求分组后各组的花费之和的最大值尽可能地小,并求这个最小值。
思路:二分答案。也就是每次设定一个最小值,看看分成m组是否能够达到。如果分组多于m,则说明mid偏小,否则说明mid偏大。
#include <stdio.h>
#include <string.h>
#define max(a,b) ((a)<(b)?(b):(a))
#define N 100005
int s[N];
int n,m;
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d %d",&n,&m)!=EOF){
int i,low,high,mid,num,sum;
low = high = 0;
for(i = 0;i<n;i++){
scanf("%d",&s[i]);
low = max(low,s[i]);//关键点之一,low如果从0开始则会出现错误
high += s[i];
}
while(low <= high){
mid = (low+high)>>1;
num = sum = 0;
for(i = 0;i<n;i++){
sum += s[i];
if(sum > mid){
num ++;
sum = s[i];
}
}
num++;//加上最后一天的组
if(num > m)
low = mid+1;
else
high = mid-1;
}
printf("%d\n",low);
}
return 0;
}
1064:
题意:给定一系列电缆的长度,需要截取成等长的m份,求所能截取的最大长度值。
思路:二分答案。注意为了避免用double,将题目中给出的小数都乘以100以变成整数再来计算即可。
2456也是同样的思路
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define N 10005
int n,m;
int s[N];
int test(int x){
int i,res=0;
for(i = 0;i<n;i++)
res += s[i]/x;
return res;
}
int main(){
int i,j,a,b;
int low,high,mid;
scanf("%d %d",&n,&m);
for(i = high = 0;i<n;i++){
scanf("%d.%d",&a,&b);
s[i] = a*100+b;
high = max(high,s[i]);
}
low = 1;
while(low <= high){
mid = (low+high)>>1;
j = test(mid);
if(j >= m)
low = mid+1;
else
high = mid-1;
}
if(high < 1)
printf("0.00\n");
else
printf("%d.%.2d\n",high/100,high%100);
return 0;
}