【NOIP2016提高A组五校联考1】挖金矿

惯例发题……

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

考场经验与分析

比赛就A了……
这道题符合二分规则(答案具有单调性)。
所以很容易想到二分答案。

正解

首先,这里涉及到一个实数域的二分(就是小数二分)。
这种二分本质上和二分答案是一样的,但是如果直接打会炸,因为小数可以无限二分(1/2,1/4,1/8,1/16,1/321/2,1/4,1/8,1/16,1/321/2,1/4,1/8,1/16,1/32……子子孙孙无穷匮也)。
所以要加一个精度dltdltdlt
一般这个dltdltdlt都是实际精度*0.1
为什么,我们再往下看代码片段

while (fabs(r-l)>dlt)//fabs就是绝对值
{
	mid=(l+r)/2;
	……
}

所以说其实就是判断两数是否达到精度极限
但是因为是判断大于,所以只能加高精度。
这样,二分问题就解决了。

还有这个数组会炸,因为只告诉我们hn&lt;=105hn&lt;=10^5hn<=105,我们10510^5105 ∗* 10510^5105会炸,
所以先读入hnhnhn,然后在主程序里inta[n+1][h+1]int a[n+1][h+1]inta[n+1][h+1](机智如我)。

那么只剩下checkcheckcheck(判断)的问题了。
我们可以使用一个O(hn)O(hn)O(hn)的方法

首先设MAXMAXMAX当前列与二分答案之差的最大值ttt当前列与二分答案之差之和sumsumsum每列与二分答案之差的最大值之和MAXMAXMAX之和)=0=0=0
接着枚举i=1……ni=1……ni=1n
{
将MAX==−mid=-mid=mid−mid-midmid就是最小值),t=0t=0t=0
然后再枚举j=1……hj=1……hj=1h
{
ttt加上差,MAXMAXMAX更新
}
sumsumsum加上MAXMAXMAX
}
如果sum&gt;=0sum&gt;=0sum>=0那就合法

这里的意思大概就是寻找每列最优解(最大),然后加起来,如果是大于等于二分答案,说明真正答案大于等于当前答案,故合法。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double dlt=0.00001;
int h,n;
double l=0,r,mid;
int main()
{
	scanf("%d%d",&n,&h);
	int a[n+1][h+1];
	for (int i=1;i<=n;i++)
		for (int j=1;j<=h;j++) scanf("%d",&a[i][j]),r=r>a[i][j]?r:a[i][j];
	while (fabs(r-l)>dlt)
	{
		mid=(l+r)/2.0;
		double MAX,t,sum=0;
    	for(int i=1;i<=n;i++)
    	{
        	MAX=-mid,t=0;
        	for(int j=1;j<=h;j++)
        	{
            	t+=a[i][j]-mid;
            	MAX=max(MAX,t);
        	}
        	sum+=MAX;
    	}
		if (sum>=0) l=mid;
		else r=mid; 
	}
	printf("%.4lf",l);
}```

有问题@我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值