Three distinct points are plotted at random on a Cartesian plane, for which -1000 ≤ x, y ≤ 1000, such that a triangle is formed.
Consider the following two triangles:
A(-340,495), B(-153,-910), C(835,-947)X(-175,41), Y(-421,-714), Z(574,-645)
It can be verified that triangle ABC contains the origin, whereas triangle XYZ does not.
Using triangles.txt (right click and ‘Save Link/Target As…’), a 27K text file containing the co-ordinates of one thousand “random” triangles, find the number of triangles for which the interior contains the origin.
NOTE: The first two examples in the file represent the triangles in the example given above.
包含原点的三角形
从笛卡尔平面中随机选择三个不同的点,其坐标均满足-1000 ≤ x, y ≤ 1000,这三个点构成一个三角形。
考虑下面两个三角形:
A(-340,495), B(-153,-910), C(835,-947)X(-175,41), Y(-421,-714), Z(574,-645)
可以验证三角形ABC包含原点,而三角形XYZ不包含原点。
在27K的文本文件triangles.txt(右击并选择“目标另存为……”)中包含了一千个“随机”三角形的坐标,找出其中包含原点在其内部的三角形的数量。
注意:文件中的前两个三角形就是上述样例。
解题
考虑了一下原点在三角形内部的三角形,原点到两个边的夹角应该有两个钝角,但是发现结果是510,表示不对,我是根据余弦定理就得costheta 这里有问题在实际中可能出现多于90度的情况然而在我计算中,我不知道怎么判断。还有个问题就是不知道我的这个想法是否有问题,下面的程序是不对的,留在这里待更改。
package Level4; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; public class PE0102{ public static void run(){ int count = 0; ArrayList<int[]> list = readData(); for(int i=0;i<list.size();i++){ int arr[] = list.get(i); if(iscontainmentTriangle(arr)){ count+=1; } if(i<10) System.out.println(iscontainmentTriangle(arr)); } System.out.println(count); } // 判断原点是否在三角形内部 public static boolean iscontainmentTriangle(int[] arr){ int count =0; for(int i=0;i<arr.length-1;i+=2){ int x1 = arr[i]; int y1 = arr[i+1]; for(int j=i+2;j<arr.length-1;j+=2){ int x2 = arr[j]; int y2 = arr[j+1]; if(isObtuseAngle(x1,y1,x2,y2)) count ++; if(count ==2) return true; } } return false; } // 是不是钝角 public static boolean isObtuseAngle(int x1,int y1,int x2,int y2){ long costheta = x1*y1 + x2*y2; if(costheta <0) return true; return false; } // 转换成整型数组 public static int [] StringtoInt(String[] strArr){ int[] IntArr = new int[strArr.length]; for(int i=0;i<strArr.length;i++) IntArr[i] = Integer.parseInt(strArr[i]); return IntArr; } // 读取数据 public static ArrayList<int[]> readData(){ String filename= "src/Level4/p102_triangles.txt"; ArrayList<int[]> list = new ArrayList<int[]>(); try { BufferedReader bufferedReader = new BufferedReader(new FileReader(filename)); String line = ""; while((line=bufferedReader.readLine())!=null){ String[] strArr = line.split(","); list.add(StringtoInt(strArr)); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } public static void main(String[] args){ long t0 = System.currentTimeMillis(); run(); long t1 = System.currentTimeMillis(); long t = t1 - t0; System.out.println("running time="+t/1000+"s"+t%1000+"ms"); } }
Java Code
mathblog 中提到了根据三角形面积相等的方式求解,ABC = ABO + ACO +BCO
这里我们知道了三角形的三个点如何根据这三个点求面积,看了下面求解的方式,根据两个向量可以快速的求出向量所组成三角形的面积S= 向量交叉相乘差的绝对值的二分之一
wiki 中有说明
【图片一直上传失败】
Java
package Level4; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; public class PE0102{ public static void run(){ int count = 0; ArrayList<int[]> list = readData(); for(int i=0;i<list.size();i++){ int arr[] = list.get(i); if(iscontainmentTria(arr)){ count+=1; } } System.out.println(count); // 228 // running time=0s16ms } // 判断原点是否在三角形内部 public static boolean iscontainmentTria(int[] arr){ int area = 0; int count =0; int X1 = arr[0] - arr[2]; int Y1 = arr[1] - arr[3]; int X2 = arr[4] - arr[2]; int Y2 = arr[5] - arr[3]; int area2 = area(X1,Y1,X2,Y2); for(int i=0;i<arr.length-1;i+=2){ int x1 = arr[i]; int y1 = arr[i+1]; for(int j=i+2;j<arr.length-1;j+=2){ int x2 = arr[j]; int y2 = arr[j+1]; area +=area(x1,y1,x2,y2); } } if(area == area2) return true; return false; } // 这里面积的二倍 public static int area(int X1,int Y1,int X2,int Y2){ int area = Math.abs(X1*Y2 - X2*Y1); return area; } // 转换成整型数组 public static int [] StringtoInt(String[] strArr){ int[] IntArr = new int[strArr.length]; for(int i=0;i<strArr.length;i++) IntArr[i] = Integer.parseInt(strArr[i]); return IntArr; } // 读取数据 public static ArrayList<int[]> readData(){ String filename= "src/Level4/p102_triangles.txt"; ArrayList<int[]> list = new ArrayList<int[]>(); try { BufferedReader bufferedReader = new BufferedReader(new FileReader(filename)); String line = ""; while((line=bufferedReader.readLine())!=null){ String[] strArr = line.split(","); list.add(StringtoInt(strArr)); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } public static void main(String[] args){ long t0 = System.currentTimeMillis(); run(); long t1 = System.currentTimeMillis(); long t = t1 - t0; System.out.println("running time="+t/1000+"s"+t%1000+"ms"); } }