3. 挖金矿
奶牛Bessie得到了一个任务——挖金矿。
这是一个深度为 hhh,宽度为 nnn 的矿场。Bessie站在地面上,第 iii 层第 jjj 列有价值为 ai,ja_{i,j}ai,j 的金矿。如图是一个 h×nh \times nh×n 的矩阵,左上角的坐标为 (1,1)(1,1)(1,1),右下角为 (h,n)(h,n)(h,n)。
对于每一列,Bessie都可以往下挖任意层。
Bessie 希望挖到的金矿的平均价值最大,请你告诉他答案吧。
输入
输入的第一行,两个整数,nnn,hhh。
接下来 nnn 行,每行 hhh 个数,第 (i+1)(i+1)(i+1) 行第 jjj 个数表示 aj,ia_{j,i}aj,i。
输出
输出挖出金矿的最大平均价值,保留 444 位小数。
样例输入
4 3
4 3 3
5 1 6
2 6 1
3 2 9
样例输出
4.4286
提示
样例解释
enter image description here
如图是一种合法方案,Bessie 决定每一列分别挖1、1、2、3层。涂色的格子代表Bessie选择挖的金矿,价值的平均值为(4+5+2+6+3+2 + 9)/7=31/7 = 4.4286。可以证明,这是最大的。
数据规模与约定
对于30%的数据,1⩽h×n⩽100,1⩽ai,j⩽1001\leqslant h \times n \leqslant 100,1\leqslant a_{i,j}\leqslant 1001⩽h×n⩽100,1⩽ai,j⩽100;
另有10%的数据,n=1n=1n=1;
对于30%的数据,1⩽h×n⩽105,1⩽ai,j⩽1091\leqslant h \times n \leqslant 10^5,1\leqslant a_{i,j}\leqslant 10^91⩽h×n⩽105,1⩽ai,j⩽109。
AC代码
import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
final static double inf = 0x7fffffff ;
public static double []qzh = new double[1000000];
public static int n;
public static int h;
public static boolean can(double mid) {
double ans = 0;
for(int i=1;i<=n;i++)
{
double s=inf*(-1);
for(int j=1;j<=h;j++)
{
double hah=j;
s=Math.max(qzh[(i-1)*h+j]-hah*mid,s);
}
ans+=s;
}
if(ans>=0)
return true;
return false;
}
public static double div()
{
double l=0;
double r=100000000000.0;
int k=500;
while(k>0)
{
k = k - 1;
double mid=(l+r)/2;
if(can(mid))
{
l=mid;
}
else
{
r=mid;
}
}
return l;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
h = scanner.nextInt();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=h;j++)
{
double x = scanner.nextDouble();
if(j!=1)
qzh[(i-1)*h+j]=qzh[(i-1)*h+j-1]+x;
else
qzh[(i-1)*h+j]=x;
}
}
DecimalFormat dec = new DecimalFormat("0.0000");
String s= dec.format(div());
System.out.println(s);
// System.out.println(div());
}
}