zzuli 20级第六次周赛 2731 问题 I: 嘟嘟的渔场

题目描述

嘟嘟是个钓鱼爱好者,他想跟好朋友嘻嘻比赛钓鱼,但是没有场地,正好嘟嘟的老家有几块矩形空地。
为了比赛的公平,嘟嘟需要建设两个形状大小均相同的矩形渔场,两个鱼塘可以建在同一块空地上,或者分别建在两块不同的空地上,同时为了能放下更多的鱼,需要渔场的面积尽量大。
已知嘟嘟的老家有n块矩形空地,每个空地的长宽分别为ai和bi (1 ≤ i ≤ n)。
请你帮嘟嘟求出他能建设的渔场的最大面积(单个鱼塘的面积)。 
注意:嘟嘟所建的渔场的边和空地的边是平行的,不需要考虑在矩形中斜着建设。

输入

第一行输入一个整数 n ,代表空地的个数。

第二行输入 n 个整数ai,代表第i块空地的长度。

第三行输入 n 个整数bi,代表第i片空地的宽度。

(1 ≤ n ≤ 105 , 1 ≤ ai , bi ≤ 104)

注意,给出的数据均满足ai ≥ bi (1 ≤ i ≤ n),并且已经按照 ai 升序排序,即 ai ≤ ai+1 (1 ≤ i < n) b不一定有序.

输出

输出单个渔场的最大面积,结果保留1位小数。

样例输入

3
3 4 8
1 4 7

样例输出

28.0

提示

样例解释:
在第三块空地建两块形状相同的鱼塘面积最大,每个鱼塘面积是28.0

思路

由题知,鱼塘可以在一块地上也可以在两块地上;如果在一块地上鱼塘要想最大就必须是单体面积最大的鱼塘除以二,而如果是两块不同的地上时,题目要求面积形状一样,所以找两两之间公共面积最大的值,再和单体面积最大的鱼塘的面积除以二比较,谁大,输出谁;

难点

本题一大难点就是两两之间的公共面积怎么算,如果暴力枚举的话时间会超限,这时看看给的数据的条件,不难想到一个取巧的方法,此方法类似动态规划(我自己觉得),如下;

对于两两间的公共面积来说是两者长,宽较小的那一边的乘积;但题目已经将一边的长度按升序给出,设两个边长为x[a].a和x[a].b,a为元素个数;x[a].a已经排好,那么x[a].a于x[a-1].a,必定以x[a-1].a的长度为公共边,另一个公共边是min(x[a].b,x[a-1].b);两者相乘得出一边为x[a-1].a时的最大公共面积,以此类推找到一边为x[a-2].a时的公共面积最大值等等,再从这一对公共面积中找到最大的那个拿去比较

注:边为x[a-2].a时,另一边为 min ( x[a-2].b , max ( x[a].b , x[a-1].b ) );如果不理解,举个例子,x[a].b=5;  x[a-1].b=1; x[a-2].b=6;  你说是取5能得最大值还是取1能;

代码

C语言

#include<stdio.h>
#include<math.h>
struct message{
    double a;
    double b;
    double c;    //c是面积
};
int main()
{
    int a,b,c,d,e;
    double max=0,l;
    scanf("%d",&a);
    struct message x[a],y;
    for(b=0;b<a;b++)
    scanf("%lf",&x[b].a);
    for(b=0;b<a;b++)
    {
        scanf("%lf",&x[b].b);
        x[b].c=x[b].b*x[b].a;
    }
    for(b=0;b<1;b++)    //找单个面积最大的,赋值于l
    {
        d=b;
        for(c=b+1;c<a;c++)
        if(x[d].c<x[c].c)
        d=c;
        l=x[d].c;
    }
    for(b=a-1;b>=1;b--)
    {
        if(x[b-1].a*fmin(x[b].b,x[b-1].b)>max)
        max=x[b-1].a*fmin(x[b].b,x[b-1].b);
        x[b-1].b=fmax(x[b].b,x[b-1].b);      //状态转移方程?应该是
    }
    if(l/2>max)
    printf("%.1lf",l/2);
    else
    printf("%.1lf",max);
 } 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值