列表

详情


NC21845. Problem C. Wpremig的三角形

描述

又快到Jhadgre的生日了,去年生日Wpremig把一张纸剪成两张一模一样的图形当成生日礼物,被喷的非常惨。于是今年Wpremig有了一个新的点子!既然剪开不行,那就拼! 于是Wpremig准备买一张很大的长方形纸板,准备在上面贴上各种形状的贴纸,来拼成一幅大的图画送给Jhadgre。可惜Wpremig去商店里买贴纸的时候,被告知店里现在只剩下了各种各样的锐角三角形和直角三角形贴纸和一张非常大的长方形纸板。

“看来这是天意呀!”,于是Wpremig就清空了商店里的所有物品......

现在Wpremig手上有N张三角形的贴纸,和一张长为101000,宽为L 的长方形纸板(纸板够大,诚意才够!),但是他又有急事要去做,所以只能麻烦你帮他完成这副图画。在多次交互之后Wpremig都没有明确表现出他到底想要一个什么样的图案,但是又急着出门,索性破罐子破摔,只要纸板上被贴上贴纸的面积越大,那就越好! 但是强迫症患者Wpremig要求在贴的时候,在两条宽边中选择一条,所有三角形贴纸必须要有一条边跟这个这条宽所在的直线重合。(贴纸超出纸板的部分面积不算,并且贴纸可以重叠,但重叠部分不计算多次面积)



因为纸板实在太大,Wpremig怕贴完之后的效果不满意,所以他想在你贴之前先知道纸板上最多能有多少面积被贴纸覆盖,这样的话万一贴完之后Wpremig不满意,也省的浪费材料,也省的你做无用功。所以请你告诉他,最多能有多少面积被覆盖呢?

输入描述

一行一个整数T(T<=10),代表数据组数。
对于每组数据:第一行是两个整数N,L(N<=100000,L<=1000000)分别代表贴纸数量与纸板的宽度(如题)。
下面N行每行三个整数ai,bi,ci(0<ai<=bi<=ci<=1000000,ai2+bi2≥ci2)表示第i张三角形贴纸的三条边长。

输出描述

对于每组数据:每行一个实数代表纸板上最多能被贴到的面积。
答案四舍五入到小数点后三位

示例1

输入:

1
2 4
3 4 5
3 4 5

输出:

10.667

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 682ms, 内存消耗: 20120K, 提交时间: 2019-01-04 14:46:24

#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const int maxn = 100010;
 
int T, cas = 1, n;
double r, a[maxn], b[maxn], c[maxn];
double area[maxn], height[maxn];
 
double f(double h)
{
    double ret = 0;
    for (int i=1;i<=n;i++)
        if (h < height[i]) ret += a[i] * (1.0 - h / height[i]);
    return ret;
}
 
int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%lf", &n, &r);
        for (int i=1;i<=n;i++) scanf("%lf%lf%lf", &a[i], &b[i], &c[i]);
        for (int i=1;i<=n;i++)
        {
            double p = (a[i] + b[i] + c[i]) / 2;
            area[i] = sqrt(p * (p-a[i]) * (p-b[i]) * (p-c[i]));
            height[i] = area[i] * 2 / a[i];
        }
        double low = 0, high = 1000000, mid;
        while ( fabs(high - low) > eps )
        {
            mid = (low + high) / 2;
            if (f(mid) <= r) high = mid;
            else low = mid;
        }
        double ans = 0, h = mid;
        for (int i=1;i<=n;i++)
            if (h < height[i]) ans += a[i] * (1.0 - h / height[i]) * (height[i] - h) / 2;
        printf("%.3lf\n", ans + h * r);
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 532ms, 内存消耗: 4452K, 提交时间: 2020-03-16 21:44:23

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100010;
const double eps=1e-8;
double a[maxn],b[maxn],c[maxn],h[maxn],area[maxn];
int n;
double len;
int t;
double f(double k)
{
	double ret=0;
	for(int i=1;i<=n;i++)
	{
		if(k<h[i])
		{
			ret+=a[i]*(1.0-k/h[i]);
		}
	}
	return ret;
}
int main()
{
	int i;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%lf",&n,&len);
		for(i=1;i<=n;i++)
		{
			scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
			double p=(a[i]+b[i]+c[i])/2;
			area[i]=sqrt(p*(p-a[i])*(p-b[i])*(p-c[i]));
			h[i]=area[i]*2.0/a[i]; 
		}
		double mid,l=0,r=100000;
		while(fabs(r-l)>eps)
		{
			mid=(l+r)/2.0;
			if(f(mid)<=len)
			{
				r=mid;
			}
			else
			{
				l=mid;
			}
		}
		double ans=0;
		for(i=1;i<=n;i++)
		{
			if(mid<h[i])
			{
				ans+=a[i]*(1.0-mid/h[i])*(h[i]-mid)/2.0;
			}
		}
		ans+=mid*len;
		printf("%.3f\n",ans);
	}
}

上一题