一、轟炸問題
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個整數x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < 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-m)s+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, 最大表示2的32次方減一,輸出格式%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;
}*/