题目描述
嘟嘟是个钓鱼爱好者,他想跟好朋友嘻嘻比赛钓鱼,但是没有场地,正好嘟嘟的老家有几块矩形空地。
为了比赛的公平,嘟嘟需要建设两个形状大小均相同的矩形渔场,两个鱼塘可以建在同一块空地上,或者分别建在两块不同的空地上,同时为了能放下更多的鱼,需要渔场的面积尽量大。
已知嘟嘟的老家有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);elseprintf("%.1lf",max);}