【XJOI】NOIP2016提高组冲剌题1 T1 挖金矿

来源:互联网 发布:php json 储存数据 编辑:程序博客网 时间:2024/06/10 05:52

这里写图片描述

这是个数学题……
设第i列前缀和sum[i],每列选的深度为h[i],每列选的总和就是sum[i][h[i]]
平均值就是:ni=1sum[i][h[i]]ni=1h[i]
显然平均值>0
设平均值为x,移项则有:

i=1n(sum[i][h[i]]h[i]x)0

能让这个式子成立的答案才是正确答案
能成立而且尽可能大的答案才是更优答案
于是就二分啦

//据说这是01分数规划 可是我并不会这个东西
//QAQ我就是当数学题做的呀

代码如下

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>using namespace std;const int MAXN = 110005;int h,n,num[MAXN];long long sum[MAXN];double l = 0,r,mid,s,mx;//一定注意精度int main(){    scanf("%d %d",&n,&h);    for(int i = 1; i <= n; i ++)        for(int j = 1; j <= h; j ++)        {            int k = (i - 1) * h + j;//二维抽象成一维以后的坐标            scanf("%d",&num[k]);            if(num[k] > r)   r = num[k];            if(j != 1)  sum[k] = sum[k - 1] + num[k];            else    sum[k] = num[k];        }    l = 0;    while(l + 0.000001 < r)//二分    {        mid = (l + r) / 2;        s = 0;        for(int i = 1; i <= n; i ++)        {            mx = -2147483645;            for(int j = 1; j <= h; j ++)                mx = max(mx,sum[(i - 1) * h + j] - j * mid);//尽可能最大            s += mx;        }        if(s >= 0)   l = mid;        else    r = mid;    }    printf("%.4lf",mid);//精度精度精度    return 0;}
2 0
原创粉丝点击