HDU-6398-Pizza Hub(枚举+计算几何)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6398

题目大意:给出一个无限长,w宽的纸带,将一个三角形放在纸带上,使得纸帯的使用长度最短,输出最短情况,如果不能放上面,输出“impossible”。

思路:我们可以将纸带竖过来,然后取一点顶在纸带的边界,然后对他进行旋转,会有以下三种情况:

如图所示,1.灰线上的是能够在两条线之间的情况,排除C点出边界,刷新h即可(可以使用向量乘法进行判断是否出界)。

2.当要斜着放的时候,以A为底,所有超过边界的都是不合法的。

枚举所哟的情况即可。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-10;

struct Point{
	double x,y;
	Point(double _x=0.0,double _y=0.0){
		x=_x;y=_y;
	}
	friend Point operator - (Point a,Point b){
		return Point(a.x-b.x,a.y-b.y);
	}
	friend double operator * (Point a,Point b){
		return a.x*b.x+a.y*b.y;
	}
	friend double operator ^ (Point a,Point b){
		return a.x*b.y-a.y*b.x;
	}
	void Input(){
		scanf("%lf%lf",&x,&y);
	}
};
Point A,B,C;
double W,Ans,Area;

double Distance2(Point a,Point b){
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double Distance(Point a,Point b){
	return sqrt(Distance2(a,b));
}
void Solve(Point a,Point b){
	if((a*b)<EPS) return ;//钝角 
	if((a*a)<W*W+EPS){//可以横着放 
		if((a*b)*(a*b)>W*W*(a*a)) return ;
		double h=Area/sqrt(a*a);
//		printf("Ans=%lf h=%lf\n",Ans,h);
		Ans=min(Ans,h);
		return ;
	}
	//需要斜着放 
	double h1=sqrt((a*a)-W*W);
	double Ang1=atan2(h1,W);
	double Ang2=asin(Area/(sqrt(a*a)*sqrt(b*b)));
	if((a^b)>=0){
		if(Ang1+Ang2>PI/2.0+EPS) return ;
		if(sqrt(b*b)*cos(Ang1+Ang2)>W+EPS) return ;
		double h2=sqrt(b*b)*sin(Ang1+Ang2);
	//	printf("Ans=%lf h=%lf\n",Ans,h);
		Ans=min(Ans,max(h1,h2));	
		return ;
	}
	if(Ang2>Ang1+EPS) return ;
	if(sqrt(b*b)*cos(Ang1-Ang2)>W+EPS) return ;
	Ans=min(Ans,h1);
}
int main(){
//	printf("%lf\n",atan2(sqrt(3),1));
	int T;scanf("%d",&T);
	while(T--){
		A.Input();B.Input();C.Input();
		scanf("%lf",&W);
		Area=fabs((B-A)^(C-A));
//		printf("Area=%lf\n",Area);
//		double AB=Distance(A,B),AC=Distance(A,C),BC=Distance(B,C);
//		if(Area*2.0/AB>W+EPS&&Area*2.0/AC>W+EPS&&Area*2.0/BC>W+EPS){
//			printf("impossible\n");continue;
//		}
		Ans=INF32;
		Solve(B-A,C-A);Solve(A-B,C-B);//AB*AC BA*BC
		Solve(A-C,B-C);Solve(C-A,B-A);//CA*CB AC*AB
		Solve(C-B,A-B);Solve(B-C,A-C);//BC*BA CB*CA
		A.x=-A.x;B.x=-B.x;C.x=-C.x;
		Solve(B-A,C-A);Solve(A-B,C-B);//AB*AC BA*BC
		Solve(A-C,B-C);Solve(C-A,B-A);//CA*CB AC*AB
		Solve(C-B,A-B);Solve(B-C,A-C);//BC*BA CB*CA
		if(fabs(Ans-INF32)<EPS) printf("impossible\n");
		else printf("%.9lf\n",Ans);
	}
}

/*

999
0 0 30 0 0 40 24
0 0 30 0 0 40 25
0 0 30 0 0 40 30
0 0 30 0 0 40 40
0 0 30 0 0 40 50
0 0 30 0 0 40 23
0 0 7 3 8 7  8
0 0 7 3 8 7 8
0 0 3 9 8 7 8
0 0 60 41 80 40 80

*/

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值