计蒜客——分组

xiaoxiao2021-02-28  42

题目描述: 对于一串数 numnumnum ,比如 num=[1,3,4,7,1,4,3,8]num=[1,3,4,7,1,4,3,8]num=[1,3,4,7,1,4,3,8] ,可以将数组中连续若干个数合并为一组 gig_igi 。将这串数组分成至多 kkk 组,当 k=4k = 4k=4 的时候,每组数的乘积的最大值 max(gi)\max(g_i)max(gi) 最小是多少?

输入格式

输入第一行一个整数 n,k(1≤n,k≤10000,0≤⌈nk⌉≤10)n, k (1 \le n, k \le 10000, 0 \le \lceil\frac{n}{k}\rceil \le 10)n,k(1n,k10000,0kn10)

接下来一行输入 nnn 个空格隔开的整数 li(1≤li≤9)l_i(1 \le l_i \le 9)li(1li9),表示数组中数的值。

输出格式

输出每组数的乘积的最大值最小是多少。

样例输入1 4 3

8 4 3 7 样例输出1 12

样例输入2 8 3

2 3 4 2 4 2 4 8 样例输出2 32

题目分析:分析:当k越大时,即分组越多时,max(gi)会越来越小(有时不变,但一定不会增大)。故k和max(gi)呈现负相关的关系。 方法分析:二分搜索+贪心 #include <iostream> #include <cmath> #define maxn 100000 using namespace std; long long s[maxn],n; bool guess(long long mid,long long s[],long long k) {//最大值为mid时,k最小 long long sum=1; for(int i=0;i<n;i++){//一共有k个箱子,箱子的最大容量为mid if(sum*s[i]>mid){//箱子装不下了,需要换下一个箱子来装 --k; sum=s[i];//(等价于sum=0,sum+=s[i]) if(s[i]>mid){//箱子装不下s[i]这件物品 return false; } }else{ sum*=s[i]; } } return k>=1;//最后需要留下一个箱子装sum里的物品 } int main() { long long k; cin>>n>>k; for(int i=0;i<n;i++){ cin>>s[i]; } long long left=1; long long ans; long long right=10e10+1;//n/k<=10,查找的上界限最大只会是10e10。 while(left<right){ long long mid=(left+right)/2; if(guess(mid,s,k)){//猜测mid是符合要求的ans ans=mid; right=mid;//如果k和max(gi)是正相关的关系,则left=mid;这里是负相关的关系,所以是right=mid; }else{ left=mid+1;//同上 } } cout<<(ans)<<endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-2619776.html

最新回复(0)