zoukankan      html  css  js  c++  java
  • BZOJ 1091--切割多边形(几何&枚举)

    1091: [SCOI2003]切割多边形

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 356  Solved: 157
    [Submit][Status][Discuss]

    Description

      有一个凸p边形(p<=8),我们希望通过切割得到它。一开始的时候,你有一个n*m的矩形,即它的四角的坐标分别为(0,0), (0,m), (n,0), (n,m)。每次你可以选择一条直线把当前图形切割成两部分,保留其中一个部分(另一部分扔掉)切割线的长度为此直线在多边形内部的部分的长度。求出最短的切割线总长度。下面是一个例子。

      分别沿着直线1,2,3,4进行切割即可,得到中间的四边形。

    Input

      第一行有两个整数n, m(0 < n,m < 500),第二行为一个整数p(3<=p<=8)。以下p行每行为两个整数x, y(0 < x< n, 0 < y < m),为按顺时针给出的各顶点坐标。数据保证多边形的是凸的,无三点共线。输入数据无错误。

    Output

      仅一行,为最短切割线的总长度,四舍五入到小数点后3位。允许有0.001的误差。

    Sample Input

    100 100
    4
    80 80
    70 30
    20 20
    20 80

    Sample Output

    312.575

    HINT

    样例对应于图中给出的例子。

    题目链接:

        http://www.lydsy.com/JudgeOnline/problem.php?id=1091 

    Solution

        心态都打崩了。。。调了一个多小时。。。。

        感觉思路和网上其他题解很像啊。。。为什么代码量差这么多。。。

        我打了5k+字的代码呀。。。。然而别人只用不到2k字就过了。。。。。。。

        我的思路是枚举切割顺序,然后强行计算答案。。。。

        因为边数小于8,所以最多只有8!个答案。。。

        至于答案的计算方法。。。。

        我是先计算出每两条边的交点,显然平行边是没有交点的于是特判掉。。。

        然后枚举切割顺序,计算每条边的最小切割长度。。。

        于是就会有一个问题:每一次的交点会在当前线段的那一端?

        根据直线函数 y = k * x + b ,说明 x + y 的值一定是有单调性的,于是比较一下当前点和线段两端点的横纵坐标和即可。。。

        但这个定理有个反例: 当 k = -1 的时候 x + y 的值是不变的,这个特例也要特判。。。。

        然后就可以了。。。。感觉似乎网上有简单的多的方法。。。心态已崩。。。。。。。。。

        请允许我贴上我那又长又臭的代码。。。。。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    inline int Read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,p;
    double ans,inf;
    int q[10];
    bool vis[10];
    struct dt{
        double x,y;
    }d[10],D[5],mp[10][10],MP[10][5];
    struct edge{
        double son1x,son1y;
        double son2x,son2y;
        int ty1,ty2;
        double k,b,s;
    }e[10],E[5];
    void calc_edge(edge &t){
    	t.ty1=t.ty2=0;
    	t.s=t.son1x+t.son1y+t.son2x+t.son2y;
    	if(t.son1x+t.son1y>t.son2x+t.son2y){
    		swap(t.son1x,t.son2x);
    		swap(t.son1y,t.son2y);
    	}
    	if(t.son1y==t.son2y) t.ty1=1;
    	else if(t.son1x==t.son2x) t.ty2=1;
    	else{
    		t.k=(double)(t.son1y-t.son2y)/(double)(t.son1x-t.son2x);
    		t.b=(double)t.son1y-(double)t.son1x*t.k;
    	}
    }
    dt calc_dt(edge A,edge B){
    	dt re;
    	if(A.ty1){
    		if(B.ty1){re.x=re.y=inf;return re;}
    		re.y=A.son1y;
    		if(B.ty2){re.x=B.son1x;return re;}
    		re.x=(re.y-B.b)/B.k;
    		return re;
    	}
    	if(A.ty2){
    		if(B.ty2){re.x=re.y=inf;return re;}
    		re.x=A.son1x;
    		if(B.ty1){re.y=B.son1y;return re;}
    		re.y=re.x*B.k+B.b;
    		return re;
    	}
    	if(B.ty1){re.y=B.son1y;re.x=(re.y-A.b)/A.k;return re;}
    	if(B.ty2){re.x=B.son1x;re.y=re.x*A.k+A.b;return re;}
    	if(B.k==A.k){re.x=re.y=inf;return re;}
    	re.x=(B.b-A.b)/(A.k-B.k);re.y=re.x*A.k+A.b;return re;
    }
    double len(double x1,double y1,double x2,double y2){
    	return (double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    void CALC(){
    	double Ans=0;
    	dt L,R,now;
    	for(int i=1;i<=p;i++){
    		L.x=L.y=R.x=R.y=inf;
    		if(e[q[i]].ty1 || e[q[i]].ty2 || (e[q[i]].k!=-1)){
    			for(int j=1;j<=4;j++){
    				now=MP[q[i]][j];
    				if(now.x==inf && now.y==inf)continue;
    				if((double)2*(now.x+now.y)>(double)e[q[i]].s){
    					if(R.x==inf && R.y==inf) R=now;
    					else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
    				}
    				else{
    					if(L.x==inf && L.y==inf) L=now;
    					else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
    				}
    			}
    			for(int j=1;j<i;j++){
    				now=mp[q[i]][q[j]];
    				if(now.x==inf && now.y==inf)continue;
    				if((double)2*(now.x+now.y)>(double)e[q[i]].s){
    					if(R.x==inf && R.y==inf) R=now;
    					else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
    				}
    				else{
    					if(L.x==inf && L.y==inf) L=now;
    					else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
    				}
    			}
    		}
    		else{
    			for(int j=1;j<=4;j++){
    				now=MP[q[i]][j];
    				if(now.x==inf && now.y==inf)continue;
    				if((double)2*now.x>(double)e[q[i]].son1x+e[q[i]].son2x){
    					if(R.x==inf && R.y==inf) R=now;
    					else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
    				}
    				else{
    					if(L.x==inf && L.y==inf) L=now;
    					else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
    				}
    			}
    			for(int j=1;j<i;j++){
    				now=mp[q[i]][q[j]];
    				if(now.x==inf && now.y==inf)continue;
    				if((double)2*now.x>(double)e[q[i]].son1x+e[q[i]].son2x){
    					if(R.x==inf && R.y==inf) R=now;
    					else if(len(R.x,R.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))R=now;
    				}
    				else{
    					if(L.x==inf && L.y==inf) L=now;
    					else if(len(L.x,L.y,e[q[i]].son2x,e[q[i]].son2y)>len(now.x,now.y,e[q[i]].son2x,e[q[i]].son2y))L=now;
    				}
    			}
    		}
    		Ans=Ans+len(L.x,L.y,R.x,R.y);
    	}
    	if(Ans<ans) ans=Ans;
    }
    void dfs(int cs){
    	if(cs>p){CALC();return;}
    	for(int i=1;i<=p;i++){
    		if(vis[i])continue;
    		vis[i]=1;
    		q[cs]=i;
    		dfs(cs+1);
    		vis[i]=0;
    	}
    	return;
    }
    int main(){
    	inf=10000000000.0;
    	ans=inf;
        n=Read();m=Read();p=Read();
        D[1].x=(double)0;D[1].y=(double)0;D[2].x=(double)0;D[2].y=(double)m;
        D[3].x=(double)n;D[3].y=(double)m;D[4].x=(double)n;D[4].y=(double)0;
        for(int i=1;i<4;i++){
        	E[i].son1x=D[i].x;E[i].son1y=D[i].y;
        	E[i].son2x=D[i+1].x;E[i].son2y=D[i+1].y;
    	}
    	E[4].son1x=D[4].x;E[4].son1y=D[4].y;
    	E[4].son2x=D[1].x;E[4].son2y=D[1].y;
    	for(int i=1;i<=4;i++) calc_edge(E[i]);
        for(int i=1;i<=p;i++){
    		d[i].x=(double)Read();d[i].y=(double)Read();
    	}
        for(int i=1;i<p;i++){
        	e[i].son1x=d[i].x;e[i].son1y=d[i].y;
        	e[i].son2x=d[i+1].x;e[i].son2y=d[i+1].y;
    	}
    	e[p].son1x=d[p].x;e[p].son1y=d[p].y;
    	e[p].son2x=d[1].x;e[p].son2y=d[1].y;
    	for(int i=1;i<=p;i++) calc_edge(e[i]);
    	for(int i=1;i<=p;i++)
    		for(int j=1;j<=p;j++)
    			if(i!=j) mp[j][i]=mp[i][j]=calc_dt(e[i],e[j]);
    	for(int i=1;i<=p;i++)
    		for(int j=1;j<=4;j++)
    			MP[i][j]=calc_dt(e[i],E[j]);
    	dfs(1);
        printf("%0.3lf
    ",ans);
        return 0;
    }
    

      

      

    This passage is made by Iscream-2001.

  • 相关阅读:
    Android Studio连接真机
    day 4 __all__ 包 __init__.py
    day1 创建X00001文件1K
    day 3 模块
    day 2 异常传递 ,抛出
    day 1 异常基本功能
    day 7 __new___
    day 6 汽车4S店铺
    day 5 多态 类 静态
    day 4 继承
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/7756176.html
Copyright © 2011-2022 走看看