题目描述
又到了周末,小易的房间乱得一团糟。
他希望将地上的杂物稍微整理下,使每团杂物看起来都紧凑一些,没有那么乱。
地上一共有n团杂物,每团杂物都包含4个物品。第i物品的坐标用(ai,bi)表示,小易每次都可以将它绕着(xi,yi)逆时针旋转90∘90∘,这将消耗他的一次移动次数。如果一团杂物的4个点构成了一个面积不为0的正方形,我们说它是紧凑的。
因为小易很懒,所以他希望你帮助他计算一下每团杂物最少需要多少步移动能使它变得紧凑。
输入描述:
第一行一个数n(1 <= n <= 100),表示杂物的团数。 接下来4n行,每4行表示一团杂物,每行4个数ai, bi,xi, yi, (-104 <= xi, yi, ai, bi <= 104),表示第i个物品旋转的它本身的坐标和中心点坐标。
输出描述:
n行,每行1个数,表示最少移动次数。
示例1
输入
4 1 1 0 0 -1 1 0 0 -1 1 0 0 1 -1 0 0 1 1 0 0 -2 1 0 0 -1 1 0 0 1 -1 0 0 1 1 0 0 -1 1 0 0 -1 1 0 0 -1 1 0 0 2 2 0 1 -1 0 0 -2 3 0 0 -2 -1 1 -2 0
输出
1 -1 3 3
说明
对于第一团杂物,我们可以旋转第二个或者第三个物品1次。
思路:简单的计算几何,考察了一定的编程能力,本题有两个难点:
1⃣️一个点逆时针旋转后的点的坐标如何求
2⃣️根据四个点判断是否为三角形
这两个难点的解决方案可以参考:题解
import java.util.*;
public class Main{
class Point implements Comparable<Point>{
int x,y,a,b;
public Point(int x,int y,int a,int b){
this.x=x;
this.y=y;
this.a=a;
this.b=b;
}
@Override
public int compareTo(Point p2){
if(x==p2.x)
return y>p2.y?1:-1;
return x>p2.x?1:-1;
}
}
public static void main(String[] args){
Main God=new Main();
int total;
Scanner in=new Scanner(System.in);
total=in.nextInt();
Point[] points=new Point[4];
for(int i=0;i<total;i++){
for(int j=0;j<4;j++){
points[j]=God.new Point(0,0,0,0);
points[j].x=in.nextInt();
points[j].y=in.nextInt();
points[j].a=in.nextInt();
points[j].b=in.nextInt();
}
int count=Integer.MAX_VALUE;
for(int m=0;m<4;m++)
for(int n=0;n<4;n++)
for(int p=0;p<4;p++)
for(int q=0;q<4;q++){
if(God.isSquare(God.rotate(points[0],m),God.rotate(points[1],n),
God.rotate(points[2],p),God.rotate(points[3],q)))
count=Math.min(count,m+n+p+q);
}
if(count==Integer.MAX_VALUE)
System.out.println(-1);
else
System.out.println(count);
}
}
private boolean isSquare(Point p1,Point p2,Point p3,Point p4){
Point[] p=new Point[4];
p[0]=p1;
p[1]=p2;
p[2]=p3;
p[3]=p4;
Arrays.sort(p);
int d1=this.dis(p[0],p[1]);
int d2=this.dis(p[0],p[2]);
int d3=this.dis(p[1],p[3]);
int d4=this.dis(p[2],p[3]);
if(d1==d2 && d2==d3 && d3==d4 && d1!=0 && this.isRightAngle(p[0],p[1],p[2]))
return true;
return false;
}
private int dis(Point a,Point b){
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
private boolean isRightAngle(Point a,Point b,Point c){
int x=(a.x-b.x)*(a.x-c.x)+(a.y-b.y)*(a.y-c.y);
return x==0;
}
private Point rotate(Point p,int times){
int x=p.x,y=p.y,a=p.a,b=p.b;
int xx,yy;
for(int i=0;i<times;i++){
xx=a-y+b;
yy=x-a+b;
x=xx;
y=yy;
}
return new Point(x,y,a,b);
}
}