二分查找---月度开销

原创 2017年12月09日 15:32:23
来源:
http://cxsjsxmooc.openjudge.cn/2017t2winterw4/3/
题目描述:
农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 100,000) 天里每天需要的开销。
约翰打算为连续的M (1 ≤ MN) 个财政周期创建预算案,他把一个财政周期命名为fajo月。每个fajo月包含一天或连续的多天,每天被恰好包含在一个fajo月里。
约翰的目标是合理安排每个fajo月包含的天数,使得开销最多的fajo月的开销尽可能少
题目分析:
1.二分查找的核心是找到一个有序的序列,然后折半查找。很显然,题目中给定的N天的开销序列,不能进行排序否则无法把它们进行结组,进行生成一个月度。
2.那么有序的序列在哪里?
思路1:
很显然,这M个月度最小的开销就是单天开销的最大值max(N),但是这个值可能不能使这里序列结成M个月。接下来就是让扩大这个基准,及令max(N)和临近的X相加生成新的值,然后重新进行测试。这时整个“扩基”过程就演变成了枚举,时间复杂度是o(n),显然会让程序超时:思路1不可行。
思路2:
这是找到一个更好的广义的有序序列,
X0,X1,X2,...,XN
Y1 = X0+X1,Y2=Y1+X2, YN = YN-1+XN, 很显然Y是有序的;但是,我们并不需要这个细粒度的序列,只需去{N}中的最大值和sum(N)分别作为控制的左右端点即可。
while(L<=R)
{
D = (L+R)
核心操作1;序列N经过划分、结组后是否能满足M的规定
核心操作2:根据N的划分情况进行边界控制
}
核心操作1:
这里需要判断这时的序列在最大开销为D时,是否能满足M的限制,即
1.从左向右开始划分序列N;2.判断生成的月度总数和M的关系
划分方法1: 划分方法2;
sum_temp = exp[0]; sum_temp = 0;
total = 0; total = 1; 最后一项exp[N-1]没法处理
for(int i = 1;i<N;i++) for(int i = 0;i<N;i++)
{ {
sum_temp+=exp[i]; if(sum_temp+exp[i]>D)
if(sum_temp>D) {
{ sum_temp = exp[i];//重新开始计算
total++; total++; //月度
sum_temp = 0; }
i--; else
} sum_temp+=exp[i];
else if(sum_temp==D) }
{
total++;
sum_temp = 0;
}
else (最后的一项需要独立算成一个month)
{
if(i==N-1)
total++;
}
}
两种方法一个很大的区别是total的初始值,方法一从零开始计算,而方法二从一开始,其原因在于两个方法是否对最后一个月度进行统计。以方法二为例,假设最后两天是400、500,当后sum_temp = exp[N-1]就无法进入循环体,这时的sum_temp显然是一个新的月度,但total并没有自增;假设最后两天是100、300,他们也是一个月度,但是计数total也没有统计他们。
综上可知,方法二没有统计最后一个月度,所以total就从1开始计算。
方法1对i==N-1进行了控制,所有从total=0开始统计也是可以的。
核心操作二:(边界条件设置,一定要仔细,不要想当然)
通过统计后total有三种状态,total==M ,total>M, total<M。其中,其中total==M说明对N的划分满足条件,可以进一步划分。如果total>M说明划分的组数过多,即D设置的过小,需要调整左边界,在D值更大的范围内搜索;如果total<M则说明划分的组数过少,即上限D设置的过大,需要调整右边界,在D值更小的范围内搜索。
if(total>M)
L = D+1;
else
R = D-1;
参考答案:
#include<math.h>
#include<iostream>
using namespace std;
int main()
{
int N,M;
int exp[100010];
int max_exp = -1,sum = 0;
cin>>N;
cin>>M;
for(int i = 0;i<N;i++)
{
cin>>exp[i];
max_exp = max(max_exp,exp[i]);
sum+=exp[i];
}
int L = max_exp;
int R = sum;
//cout<<L<<" "<<sum<<endl;
int D,sum_temp,total,last_D=0;
while(L<=R)
{
D = (R+L)/2;
//D=500;
sum_temp = exp[0];
total = 0;
bool flag = false;
for(int i = 1;i<N;i++)
{
sum_temp+=exp[i];
if(sum_temp>D)
{
total++;
sum_temp = 0;
i--;
}
else if(sum_temp==D)
{
total++;
sum_temp = 0;
}
else
{
if(i==N-1)
total++;
}

}
//cout<<total<<endl;
if(total<=M)
{
last_D = D;
R = D-1;
}
else
L = D+1;
}
cout<<last_D;
}
不做伸手党

【OJ二分06】月度开销

月度开销 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接...
  • xym_CSDN
  • xym_CSDN
  • 2015年11月23日 20:05
  • 1292

|NOIOJ|二分|06:月度开销

描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 100,000) 天里每天需要的开销。 约翰打算为连续的M (1 ...
  • Darost
  • Darost
  • 2016年05月31日 06:36
  • 2055

06:月度开销OJ

总时间限制: 1000ms内存限制: 65536kB 描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 10...
  • sinat_34943123
  • sinat_34943123
  • 2016年05月10日 22:29
  • 810

06:月度开销OJ

总时间限制: 1000ms内存限制: 65536kB 描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 10...
  • sinat_34943123
  • sinat_34943123
  • 2016年05月10日 22:29
  • 810

|NOIOJ|二分|06:月度开销

描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 100,000) 天里每天需要的开销。 约翰打算为连续的M (1 ...
  • Darost
  • Darost
  • 2016年05月31日 06:36
  • 2055

【openjudge】月度开销 二分查找

06:月度开销总时间限制: 1000ms 内存限制: 65536kB 描述 农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ...
  • zhhe0101
  • zhhe0101
  • 2016年10月14日 20:42
  • 206

【USACO题库】5.3.4 Big Barn巨大的牛棚

题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成 N x N 的方格。输入数据中包括...
  • John_pascal
  • John_pascal
  • 2016年04月06日 22:18
  • 807

题目1204:农夫、羊、菜和狼的故事

题目描述: 有一个农夫带一只羊、一筐菜和一只狼过河. 果没有农夫看管,则狼要吃羊,羊要吃菜. 但是船很小,只够农夫带一样东西过河。 问农夫该如何解此难题? 输入: 题目没有...
  • u011885406
  • u011885406
  • 2014年08月03日 20:56
  • 1000

【选拔题】2009南海集训队初中选拔题一

首先必须要说的一点是这套题目并不难,只是时间限制有点坑,需要我们努力想才能得出算法答案。...
  • Dream_Lolita
  • Dream_Lolita
  • 2016年08月08日 09:33
  • 656

[POJ3189][cqbzoj1640]稳定的奶牛分配 解题报告

【USACO TRAING】追查坏牛奶时间限制: 1 Sec 内存限制: 64 MB题目描述你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事...
  • u013675643
  • u013675643
  • 2016年08月19日 20:20
  • 657
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二分查找---月度开销
举报原因:
原因补充:

(最多只允许输入30个字)