Tri_integral Summer Training 4
题意:
有n+1的结点的链,每条边(结点圆心距)100,每个结点半径为10,每次可以旋转45°,但是不能自交。求是否通过旋转某些结点使得最上面的结点完全包含在一个矩形内。
题解:
首先矩形每条边向内缩10,这样只要最上面的点的圆心在新矩形即可。然后枚举所有节点旋转的角度,加上判断是否自交和剪枝,不会超时的。
因为时间紧,代码写的很丑,请轻拍……
//Time:22ms
//Memory:0KB
//Length:2709B
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <set>
#include <algorithm>
#define EPS 1e-6
#define INF 1000000007
using namespace std;
struct _node
{
double num;
int ro;
bool operator <(const _node &b) const
{
if(ro!=b.ro)
return ro<b.ro;
return num<b.num-EPS;
}
};
int dcmp(double x)
{
if(fabs(x)<EPS) return 0;
return x<0? -1:1;
}
struct Point
{
double x,y;
Point(){}
Point(double a,double b):x(a),y(b){}
Point operator-(const Point &a)const{return Point(x-a.x,y-a.y);}
void input()
{
scanf("%lf%lf",&x,&y);
}
};
typedef Point Vector;
double Cross(Vector a, Vector b)
{
return a.x*b.y-a.y*b.x;
}
bool Isinter(Point s1, Point e1,Point s2,Point e2)
{
if(min(s1.x,e1.x)<=max(s2.x,e2.x)&&
min(s1.y,e1.y)<=max(s2.y,e2.y)&&
min(s2.x,e2.x)<=max(s1.x,e1.x)&&
min(s2.y,e2.y)<=max(s1.y,e1.y)&&
dcmp(Cross(s2-s1,e2-s1))*dcmp(Cross(s2-e1,e2-e1))<=0&&
dcmp(Cross(s1-s2,e1-s2))*dcmp(Cross(s1-e2,e1-e2))<=0)
return 1;
return 0;
}
bool Isin(Point a,Point b,Point c)
{
if(c.x>=a.x&&c.x<=b.x&&c.y>=a.y&&c.y<=b.y) return 1;
return 0;
}
set<_node> se[10];
int n,ans;
Point ldown,rup;
double posx[11],posy[11];
const double sqrt2=sqrt(2.0)*50.0;
double dir[8][2]={{0,100},{sqrt2,sqrt2},{100,0},{sqrt2,-sqrt2},
{0,-100},{-sqrt2,-sqrt2},{-100,0},{-sqrt2,sqrt2}};
int need[10]={0,1,2,3,4,3,2,1};
void dfs(int h,int sum,int ro,double x,double y)
{
if(sum>ans) return ;
if(h==n)
{
if(Isin(ldown,rup,Point(x,y)))
ans=min(ans,sum);
return ;
}
_node node;
node.num=x*10001+y;
node.ro=sum;
if(se[h].find(node)!=se[h].end()) return ;
se[h].insert(node);
posx[h]=x,posy[h]=y;
if(h>=3)
for(int i=h-3;i<h-2;++i)
if(Isinter(Point(posx[h],posy[h]),Point(posx[h-1],posy[h-1]),
Point(posx[i],posy[i]),Point(posx[i+1],posy[i+1])))
return ;
for(int i=0;i<8;++i)
if(i!=4)
{
int tro=(ro+i)%8;
dfs(h+1,sum+need[i],tro,x+dir[tro][0],y+dir[tro][1]);
}
return ;
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
int ncase,x,y;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
scanf("%d%d",&x,&y);
x+=10,y+=10;
ldown=Point(x,y);
scanf("%d%d",&x,&y);
x-=10,y-=10;
rup=Point(x,y);
for(int i=0;i<n;++i) se[i].clear();
ans=INF;
dfs(0,0,0,0.0,0.0);
printf("%d\n",ans==INF?-1:ans);
}
return 0;
}