Project Euler 102:Triangle containment 包含原点的三角形

Triangle containment

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");
    }
}
时间: 2024-11-08 17:21:08

Project Euler 102:Triangle containment 包含原点的三角形的相关文章

Python练习题 048:Project Euler 021:10000以内所有亲和数之和

本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable numbers Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b

Python练习题 047:Project Euler 020:阶乘结果各数字之和

本题来自 Project Euler 第20题:https://projecteuler.net/problem=20 ''' Project Euler: Problem 20: Factorial digit sum n! means n × (n ? 1) × ... × 3 × 2 × 1 For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, and the sum of the digits in the number 10! i

Python练习题 046:Project Euler 019:每月1日是星期天

本题来自 Project Euler 第19题:https://projecteuler.net/problem=19 ''' How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? Answer: 171 ''' from datetime import * firstDay = date(1901,1,1) lastDay = date(

Python练习题 035:Project Euler 007:第10001个素数

本题来自 Project Euler 第7题:https://projecteuler.net/problem=7 # Project Euler: Problem 7: 10001st prime # By listing the first six prime numbers: # 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. # What is the 10 001st prime number? # Answer

Python练习题 034:Project Euler 006:和平方与平方和之差

本题来自 Project Euler 第6题:https://projecteuler.net/problem=6 # Project Euler: Problem 6: Sum square difference # The sum of the squares of the first ten natural numbers is, # 1**2 + 2**2 + ... + 10**2 = 385 # The square of the sum of the first ten natur

Project Euler 126 - Cuboid layers

这题先是推公式- 狂用不完全归纳+二次回归,最后推出这么一个奇怪的公式 f(t,x,y,z)=4(t?1)(x+y+z+t?2)+2(xy+yz+xz) 表示长宽高为x .y .z 的立方体第t 层放的立方体的个数. 接下来就是算答案了- 方法很简单:暴力 但是暴力还是有技巧的,开始我是直接从1到1000枚举t .x .y .z ,但这样出不来结果. 换成下面代码里的方法就行了. 1 #include <iostream> 2 #include <cstdio> 3 #includ

Project Euler 第一题效率分析

Project Euler: 欧拉计划是一系列挑战数学或者计算机编程问题,解决这些问题需要的不仅仅是数学功底. 启动这一项目的目的在于,为乐于探索的人提供一个钻研其他领域并且学习新知识的平台,将这一平台打造一个有趣和休闲 的环境. 项目主页:https://projecteuler.net 第一题 Multiples of 3 and 5 If we list all the natural numbers below 10 that are multiples of 3 or 5, we ge

Python练习题 042:Project Euler 014:最长的考拉兹序列

本题来自 Project Euler 第14题:https://projecteuler.net/problem=14 ''' Project Euler: Problem 14: Longest Collatz sequence The following iterative sequence is defined for the set of positive integers: n → n/2 (n is even) n → 3n + 1 (n is odd) Using the rule

Python练习题 041:Project Euler 013:求和、取前10位数值

本题来自 Project Euler 第13题:https://projecteuler.net/problem=13 # Project Euler: Problem 13: Large sum # Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. # Answer: 5537376230 numbers = '''371072875339021027987979982