• BZOJ 1859 Luogu P2589 [ZJOI2006]碗的叠放 (计算几何)


    woc, 13年前的ZJOI就这么毒瘤的嘛。。。

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=1859

    (luogu)https://www.luogu.org/problemnew/show/P2589

    题解: 大分类讨论,预处理(ints[i][j])表示碗(i)叠在(j)上,(i)的底部比(j)的底部要高多少

    然后分类讨论求此数组:

    (1) (i)的下半径比(j)的上半径大,则等于(j)的高度

    (2) (i)的上半径比(j)的下半径小,则等于零

    (3) (i)的碗壁斜率大于(j)的碗壁斜率

    (3.1) 若(i)的下半径小于等于(j)的下半径,则为零

    (3.2) 若(i)的下半径大于(j)的下半径,则接触点横坐标为(i)的下半径,通过(j)的一次函数计算高度即可

    (4) (i)的碗壁斜率小于(j)的碗壁斜率

    (4.1) 若(i)的上半径大于等于(j)的上半径,则接触点为(j)的口处,通过(i)的一次函数计算高度

    (4.2) 若(i)的上半径小于(j)的上半径,则(不妨先不考虑碗底)接触点横坐标为(i)的上半径,通过(j)的一次函数计算高度

    情况(4)最后求出来的高度和(0)取Max.

    (5) 若(i)(j)碗壁斜率相等

    (5.1) 若(i)的下半径小于等于(j)的下半径,则高度为(0).

    (5.2) 若(i)的下半径大于(j)的上半径,则接触点横坐标为(i)的下半径,通过一次函数计算高度即可。

    然后一个显然的性质是一个碗叠在一摞碗上,它的叠放高度为和每个碗分别叠放的高度的Max.

    时间复杂度(O(n! imes n))

    这题……我还能说什么呢23333

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cassert>
    #include<algorithm>
    using namespace std;
    
    const int N = 9;
    struct Element
    {
    	int h,r1,r2;
    	double calc(double x) {return h*(x-(double)r1)/((double)r2-r1);}
    } a[N+3];
    double hh[N+3];
    int permu[N+3];
    double ints[N+3][N+3];
    int n;
    
    double intersect(int x,int y)
    {
    //	printf("Intersect (%d,%d)
    ",x,y);
    	double ret;
    	if(a[x].r1>a[y].r2) {ret = a[y].h;/* printf("Case 1
    ");*/}
    	else if(a[x].r2<a[y].r1) {ret = 0;/* printf("Case 2
    ");*/}
    	else if((a[y].r2-a[y].r1)*a[x].h>(a[x].r2-a[x].r1)*a[y].h)
    	{
    		if(a[x].r1<=a[y].r1) {ret = 0;/* printf("Case 3.1
    ");*/}
    		else {ret = a[y].calc((double)a[x].r1);/* printf("Case 3.2
    ");*/}
    	}
    	else if((a[y].r2-a[y].r1)*a[x].h<(a[x].r2-a[x].r1)*a[y].h)
    	{
    		if(a[x].r2>=a[y].r2) {ret = a[y].h-a[x].calc(a[y].r2);/* printf("Case 4.1
    ");*/}
    //		else if(a[x].h*(a[y].r2-a[y].r1)<=a[y].h*(a[x].r2-a[y].r1)) {ret = 0;}
    		else {ret = a[y].calc(a[x].r2)-a[x].calc(a[x].r2);/* printf("Case 4.2
    ");*/}
    		if(ret<0) ret = 0;
    	}
    	else
    	{
    		if(a[x].r1<=a[y].r1) {ret = 0;/* printf("Case 5.1
    ");*/}
    		else {ret = a[y].calc(a[x].r1);/* printf("Case 5.2
    ");*/}
    	}
    //	printf("ret=%lf
    ",ret);
    	return ret;
    }
    
    double calc()
    {
    //	printf("calc: "); for(int i=1; i<=n; i++) printf("%d ",permu[i]); puts("");
    	double ret = 0.0;
    	for(int i=1; i<=n; i++)
    	{
    		hh[i] = 0;
    		for(int j=1; j<i; j++)
    		{
    			hh[i] = max(hh[i],hh[j]+ints[permu[i]][permu[j]]);
    		}
    		ret = max(ret,hh[i]+a[permu[i]].h);
    	}
    //	printf("Total=%lf
    ",ret); puts("");
    	return ret;
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1; i<=n; i++) scanf("%d%d%d",&a[i].h,&a[i].r1,&a[i].r2);
    	for(int i=1; i<=n; i++) permu[i] = i;
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			if(i==j) continue;
    			ints[i][j] = intersect(i,j);
    		}
    	}
    	double ans = 1e6;
    	do
    	{
    		ans = min(ans,calc());
    	} while(next_permutation(permu+1,permu+n+1));
    
    	printf("%d
    ",(int)(ans+0.5));
    	return 0;
    }
    
  • 相关阅读:
    phpcms无法读取index.html的解决步骤
    PHPwind高级伪静态规则及方法
    WordPress 添加Meta Box的方法步骤
    WordPress实现登录或退出后直接跳转到首页的方法
    怎么在php里面利用str_replace防注入
    php strrpos()与strripos()函数不同之处在哪里呢
    smarty中增加类似foreach的功能自动加载数据方法
    php连接Access数据库错误及解决方法
    如何利用php array_multisort函数 对数据库排序
    php之XML转数组函数的方法
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11101670.html
Copyright © 2020-2023  润新知