题目链接: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
*/