码迷,mamicode.com
首页 > 其他好文 > 详细

Project Euler 91:Right triangles with integer coordinates 格点直角三角形

时间:2015-11-30 22:20:59      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:

Right triangles with integer coordinates

The points P (x1, y1) and Q (x2, y2) are plotted at integer co-ordinates and are joined to the origin, O(0,0), to form ΔOPQ.

技术分享

There are exactly fourteen triangles containing a right angle that can be formed when each co-ordinate lies between 0 and 2 inclusive; that is,0 ≤ x1, y1, x2, y2 ≤ 2.

技术分享

Given that 0 ≤ x1, y1, x2, y2 ≤ 50, how many right triangles can be formed?


格点直角三角形

点P(x1, y1)和点Q(x2, y2)都是格点,并与原点O(0,0)构成ΔOPQ。

技术分享

当点P和点Q的所有坐标都在0到2之间,也就是说0 ≤ x1, y1, x2, y2 ≤ 2时,恰好能构造出14个直角三角形。

技术分享

如果0 ≤ x1, y1, x2, y2 ≤ 50,能构造出多少个直角三角形?

 解题

 先网上找到的答案,然后看题解中,前面几题给出了暴露的方法,遍历所有的点 ,判断是否是直角三角形就好了,最后的结果要除以2,,因为两个点是可以互换的。

Java

package Level3;

public class PE091{
    static void run(){
        int N = 50;
        int count = 0;
        // 第一个顶点
        for(int x1 = 0; x1<=N;x1++){
            for(int y1 = 0;y1<=N ;y1++){
                if(x1==0 && y1==0) continue;
                // 第二个顶点
                for(int x2 = 0;x2<=N;x2++){
                    for(int y2=0;y2<=N;y2++){
                        if(x2==0&&y2==0 || x1==x2&&y1==y2)
                            continue;
                        //判断是否是三角形
                        double d1 = getDistance(0,0,x1,y1);
                        double d2 = getDistance(0,0,x2,y2);
                        double d3 = getDistance(x1,y1,x2,y2);
                        if(d1+d2==d3|| d1+d3==d2||d2+d3==d1)
                            count++;
                    }
                }
            }
        }
        System.out.println(count/2);
    }
//    14234
//    running time=0s71ms
    static double getDistance(int x1,int y1,int x2,int y2){
        double d1 = (x1-x2)*(x1-x2);
        double d2 = (y1-y2)*(y1-y2);
        return d1+d2;
    }
    
    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");

    }
}

参考链接1  参考链接2 

上面给出来很好的不用暴力的方法

对于直角在原点的情况:

P Q两点只能在x轴  y轴上,固定一点看另一点,显然有50中可能,然而这一点也有50种可能,共2500种

对于直角在x轴或者y轴的情况:

当P 在x轴上的某点时候,Q的x坐标显然要和P 的一样,PQ都各有50个位置,共2500种

当P 在y轴的时候,也有2500种

对于直角在方格内部的时候:

技术分享

要使得是直角三角形:OP要垂直PQ

OP的斜率:k = dy/dx  (dy/dx是最简分数)    其中P的坐标设为(x,y)

则PQ的斜率是:-dx/dy

如何根据斜率,找到Q的整数点,或者Q点的个数。

当P点的y轴值>Q点的y轴的值时候:

(如上图所示)可以发现:Q1 Q2 把PQ3等分成三份。三个Q点都是整数点。

对斜率为k = dy/dx :可以通过一个dy * dx的方格表示出来,所以,对于P(x,y)点,x每加一个dx y每减一个dy都是一个整数Q点,那么有多少个符合要求的点?只需要看最大能走多少步,

对于PQ的斜率是dx/dy,当P(x,y),   对x而言最大的步数是:(N-x)/dy ,对y而言最大的步数是:y/dx

这样其最小值就是Q的整数点数:MIN((N-x)/dy,y/dx)

 

当P点的y轴值<Q点的y轴的值时候:


PQ的斜率是:-dx/dy 

P(x,y) x向左走的最大步数:x/dy y向上走的最大步数:(N-y)/dx

这样其最小值就是Q的整数点数:MIN(x/dy,(N-y)/dx)

这与上面链接的结果不一样,根据运行结果发现答案是一样的

其实吧 对于P点的坐标可以是在N*N方格中的任意一点,P的坐标是可以对称的,所以可以直接乘以二的。

JAVA

package Level3;

public class PE091{
    static void run1(){
        int N = 50;
        // 直角在原点,直角在x轴 直角在y轴,个数都是N*N
        int result =N*N*3;
        //下面只需要对直角在方格内部的情况
        for(int x = 1;x<= N;x++){
            for(int y=1;y<= N;y++){
                int fact = gcd(x,y);
                result += Math.min(y*fact/x, (N-x)*fact/y);
                result += Math.min(x*fact/y, (N-y)*fact/x);
            }
        }
        System.out.println(result);
    }
//    14234
//    running time=0s78ms
    static int gcd(int x,int y){
        if(x<y){
            int tmp = x;
            x = y;
            y = tmp;
        }
        int r = x%y;
        while(r!=0){
            int tmp =x;
            x = y;
            y = tmp%x;
            r = x%y;
        }
        return y;
    }
    static void run(){
        int N = 50;
        int count = 0;
        // 第一个顶点
        for(int x1 = 0; x1<=N;x1++){
            for(int y1 = 0;y1<=N ;y1++){
                if(x1==0 && y1==0) continue;
                // 第二个顶点
                for(int x2 = 0;x2<=N;x2++){
                    for(int y2=0;y2<=N;y2++){
                        if(x2==0&&y2==0 || x1==x2&&y1==y2)
                            continue;
                        //判断是否是三角形
                        double d1 = getDistance(0,0,x1,y1);
                        double d2 = getDistance(0,0,x2,y2);
                        double d3 = getDistance(x1,y1,x2,y2);
                        if(d1+d2==d3|| d1+d3==d2||d2+d3==d1)
                            count++;
                    }
                }
            }
        }
        System.out.println(count/2);
    }
//    14234
//    running time=0s71ms
    static double getDistance(int x1,int y1,int x2,int y2){
        double d1 = (x1-x2)*(x1-x2);
        double d2 = (y1-y2)*(y1-y2);
        return d1+d2;
    }
    
    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");

    }
}

 Python

# coding=gbk

import time as time 
from itertools import combinations  
def run():
    N = 50 
    count  = N*N*3
    for x in range(1,N+1):
        for y in range(1,N+1):
            fact = gcd(x,y)
            count += min((N-x)*fact/y,y*fact/x)*2 
    print count 
            
# 14234
# running time= 0.00300002098083 s   
def gcd(x,y):
    if x<y:
        x,y = y,x
    while x%y!=0:
        tmp = x
        x = y 
        y = tmp%y 
    return y 

t0 = time.time()
run() 
t1 = time.time()
print "running time=",(t1-t0),"s"

            

 

Project Euler 91:Right triangles with integer coordinates 格点直角三角形

标签:

原文地址:http://www.cnblogs.com/theskulls/p/5008169.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!