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; }