C/C++的簡單幾何思想

一、轟炸問題
1、 依次用兩點確定一條直線,判斷後面的點是否在直線上。
2、 直線方程:(y-y1)/(x-x1)=(y2-y1)/(x2-x1)
3、 爲了防止除數爲0,將方程式變形(交叉相乘):
(y-y1)(x2-x1)=(y2-y1)(x-x1)

/*
轟炸
輸入文件: "bomb.in"  輸出文件: "estdout.pc2"
問題描述
"我該怎麼辦?"飛行員klux向你求助。事實上,klux面對的是一個很簡單的問題,但是他實在太菜了。klux要想轟炸某個區域內的一些地方,它們是位於平面上的一些點,但是(顯然地)klux遇到了抵抗,所以klux只能飛一次,而且由於飛機比較破,一點起飛就只能沿直線飛行,無法轉彎。現在他想一次轟炸最多的地方。
輸入
輸入由若干組數據構成,每組數據的第一行是整數n,然後是n行整數對組成(1<n<700),每對整數表示一個點的座標,且沒有一個點會出現兩次。當n爲0時表示輸入結束。
輸出
針對每組數據輸出一個整數,它表示一條直線能覆蓋的最多的點數。
輸入樣本
5
1 1
2 2
3 3
9 10
10 11
0
輸出樣本
3
【程序說明】
1、兩點確定一條直線
2、點點式直線方程確定直線
3、帶入法判斷第三點在不在直線上
4、轉除法爲加法
*/
#include<stdio.h>
#include "stdlib.h"
struct point
{
       int x,y;
} a[700];//平面上的點

int main()
{
    int n, maxPoint, xa, xb, xc, ya, yb, yc, tem;//n:點數 maxPoint:最大點數 tem:每條直線上的點

    maxPoint = 0;
    scanf("%d", &n);
    for (int i = 0; i <= n-1; ++i)
    {
        scanf("%d%d", &a[i].x, &a[i].y);
    }

    for (i = 0; i <= n-3; ++i)
    {
        for (int j = i+1; j <= n-2; ++j)
        {
            tem=2;
            xa=a[i].x; //起點x座標
            ya=a[i].y; //起點y座標
            xb=a[j].x; //終點x座標
            yb=a[j].y; //終點y座標
            for (int k=j+1; k<=n-1; ++k)
            {
                xc=a[k].x;
                yc=a[k].y;
                if ((yb-ya)*(xc-xa) == (yc-ya)*(xb-xa))//斜率相等
                {
                    ++tem;//點數加加
                }
            }
            if (tem > maxPoint) 
            {
                maxPoint = tem;
            }
        }
    }
    printf("%d\n",maxPoint);
    return 0;
}

二、青蛙在網上相識
1、分析題目,建立數學模型
兩個青蛙在循環跑到上追逐,各自的步長,步速不等,須在同一時刻跳到同一點,方可判斷相遇,結束。也有可能永遠不會相遇。
2、建立數學表達式:(x+sm)-(y+sn)=kL;
變型:(n-m)s+kL=x-y
在變型方程式裏面,s和k爲未知數,其餘已知;
3、哪種情況是永不相遇:根據擴展的歐幾里得原理有已知方程ax+by=c有整數解需滿足條件c%d爲0;d爲a和b的最大公約數。
4、 根據建立的數學表達式,分別求出對應的a,b,c值。
a=n-m;b=L;c=x-y;
5、 求a與b的最大公約數。
6、 如果有整數解,求經過多少步相遇。
方法一:各自一步步跳,到位置相等退出。
while(front != rear)
{

    front=(front+m) % L;
    rear=(rear+n) % L ;
    step++;
}

方法二:根據相對距離與相對速度求解。
相對距離除以相對速度,如結果不爲整數步,則加上一整圈距離再除,知道相除結果爲整數步爲止。
if((i*L + (y-x))%(m-n) == 0)
{
step = (i*L + (y-x))/(m-n);
break;
}

/*
【問題描述】
  兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面爲止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定見面的具體位置。不過青蛙們都是很樂觀的,它們覺得只要一直朝着某個方向跳下去,總能碰到對方的。但是除非這兩隻青蛙在同一時間跳到同一點上,不然是永遠都不可能碰面的。爲了幫助這兩隻樂觀的青蛙,你被要求寫一個程序來判斷這兩隻青蛙是否能夠碰面,會在什麼時候碰面。
我們把這兩隻青蛙分別叫做青蛙A和青蛙B,並且規定緯度線上東經0度處爲原點,由東往西爲正方向,單位長度1米,這樣我們就得到了一條首尾相接的數軸。設青蛙A的出發點座標是x,青蛙B的出發點座標是y。青蛙A一次能跳m米,青蛙B一次能跳n米,兩隻青蛙跳一次所花費的時間相同。緯度線總長L米。現在要你求出它們跳了幾次以後纔會碰面。
【輸入】輸入文件名"frogin.txt"
輸入只包括一行5個整數xym,n,L,其中xy < 20000000000 < m、n < 20000000000 < L < 2100000000。 
【輸出】輸出文件名"frogout.txt"
針對輸入的數據如果永遠不可能碰面則輸出一行Impossible,如果可以碰面則輸出碰面所需要的跳躍次數。
【樣例輸入】
1 2 3 4 5
【樣例輸出】
4

【程序說明】
__int64佔32爲;x:青蛙A的起始點;y:青蛙B的起點;m:青蛙A的速度;n:青蛙B的速度;
構造方程:ax+by=c;
設需要s步
由題意可知:(x+sm)-(y+sn)=kL;//L的k倍
變型:(n-ms+kL=x-y
所以:a=n-m;b=L;c=x-y*/

#include "stdio.h"

__int64 gcd(__int64 a, __int64 b)//輾轉相除法求最大公約數
{   
    if(b==0)
        return a;   
    return gcd(b,a%b);
}


int main()
{
    __int64 x, y, n, m, L, a, b, c, d, step = 0;

    printf("請輸入青蛙A所在的位置:");
    scanf("%I64d", &x);
    printf("請輸入青蛙B所在的位置:");
    scanf("%I64d", &y);

    printf("請輸入青蛙A一次跳多少米:");
    scanf("%I64d", &m);

    printf("請輸入青蛙B一次跳多少米:");
    scanf("%I64d", &n);

    printf("請輸入維度線總長:");
    scanf("%I64d", &L);

    if(n<m)
        a = m-n;
    else
        a = n-m;
    b = L;

    if(x>y)
        c=x-y;
    else
        c=y-x;

    d = gcd(a, b);

    if(m==n||c%d != 0)
    {
        printf("Impossible\n");
    }
    else
    {
        unsigned int temp;

        if(x>y)
        {
            temp = x;
            x =y;
            y = temp;
            temp = m;
            m = n;
            n = temp;
        }

        for(int i=0;;i++)
        {  
            if(m<n)
            {
                if((i*L + (L-(y-x)))%(n-m) == 0)
                {
                    step = (i*L + (L-(y-x)))/(n-m);
                    break;
                }
            }
            else if(x<y && m>n)
            {

                if((i*L + (y-x))%(m-n) == 0)
                {
                    step = (i*L + (y-x))/(m-n);
                    break;
                }
            }                    
        }   
        printf("一共跳%I64d步\n",step);
    }   

    return 0;
}


/*
#include "stdio.h"
#include "stdlib.h"

unsigned int gcd(unsigned int a, unsigned int b)//輾轉相除法求最大公約數
{   
    if(b==0)
        return a;   
    return gcd(b,a%b);
}


int main()
{
    unsigned int  front ;
    unsigned int  rear ;
    unsigned int  step = 0;//4294967295, 最大表示232次方減一,輸出格式%u
    unsigned int  x, y, n, m, L, a, b, c, d;

    printf("請輸入青蛙A所在的位置:");
    scanf("%d", &x);

    printf("請輸入青蛙B所在的位置:");
    scanf("%d", &y);

    printf("請輸入青蛙A一次跳多少米:");
    scanf("%d", &m);

    printf("請輸入青蛙B一次跳多少米:");
    scanf("%d", &n);

    printf("請輸入維度線總長:");
    scanf("%d", &L);

    if(n<m)
        a = m-n;
    else
        a = n-m;
    b = L;
    //c = x - y;    
    if(x>y)
        c=x-y;
    else
        c=y-x;

    d = gcd(a, b);

    if(m==n||c%d != 0)
    {
        printf("Impossible\n");
        return 0;
    }

    front = x;
    rear = y;

    while(front != rear)
    {

        front=(front+m) % L;
        rear=(rear+n) % L ;
        step++;
    }

    printf("%u\n", step);
    return 0;
}*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章