neoj 461
演算法邏輯如下
對所有的霸霸、咩咩、喵喵
計算他們與娃娃魚的距離
只要至少一個霸霸且至少一個咩咩且至少一個喵喵
與娃娃魚的距離小於要求 (10, 10, 12)
就可以輸出解
distance function
作法一
直接計算
sqrt() (#include <cmath>就有)
double distance(int x1, int y1, int x2, int y2){
int sqrx = (x1 - x2) * (x1 - x2);
int sqry = (y1 - y2) * (y1 - y2);
return sqrt(sqrx + sqry);
}distance function
作法二
為了避免浮點數誤差
改成透過 dis * dis 來比較距離
數學上等價
int distance(int x1, int y1, int x2, int y2){
int sqrx = (x1 - x2) * (x1 - x2);
int sqry = (y1 - y2) * (y1 - y2);
return sqrx + sqry;
}distance function
long long distance(int x1, int y1, int x2, int y2){
long long lx1, ly1, lx2, ly2;
lx1 = x1, ly1 = y1, lx2 = x2, ly2 = y2;
long long sqrx = (lx1 - lx2) * (lx1 - lx2);
long long sqry = (ly1 - ly2) * (ly1 - ly2);
return sqrx + sqry;
}
/*
int a, b;
long long c = a * b; //這樣還是會overlflow哦 因為a*b的時候就已經超過了,詳情請見轉型一章
*/順帶一提,本題的測資很友善,都不會超過int的範圍
日後實作需要int * int的問題的時候都要注意是否會在運算中 overflow
必要時候請使用 long long
distance function
long long distance(int x1, int y1, int x2, int y2){
long long sqrx = (1LL * x1 - y2) * (lx1 - lx2);
long long sqry = (1LL * y1 - y2) * (ly1 - ly2);
return sqrx + sqry;
}小小訣竅
isValid function
bool isValid(int a, int b, int c,
int baba[], int meme[], int meow[],
int x, int y){
bool getbaba, getmeme, getmeow;
getbaba = getmeme = getmeow = false;
for(int i = 0; i < a; i++) {
double disbaba = distance(x, y, baba[i * 2], baba[i * 2 + 1]);
if (disbaba <= 10.0) {
getbaba = true;
break;
}
}
/* ... */
if(getmeow && getmeme && getbaba)
return true;
return false;
}
這邊只示範 霸霸
isValid function
for(int i = 0; i < a; i++) {
double disbaba =
distance(x, y, baba[i * 2], baba[i * 2 + 1]);
if (disbaba <= 10.0) {
getbaba = true;
break;
}
}
重點部分
isValid function
const double eps = 1e-8;
int dcmp(double a, double b){
if(fabs(a - b) <= eps)
return 0;
if(a - b > 0) return 1;
else return -1;
}
for(int i = 0; i < a; i++) {
double disbaba =
distance(x, y, baba[i * 2], baba[i * 2 + 1]);
if (dcmp(disbaba,10.0) <= 0) {
getbaba = true;
break;
}
}
浮點數比較建議作法 (有點進階)
isValid function
int distance(int x1, int y1, int x2, int y2){
int sqrx = (x1 - x2) * (x1 - x2);
int sqry = (y1 - y2) * (y1 - y2);
return sqrx + sqry;
}
for(int i = 0; i < a; i++) {
int disbaba =
distance(x, y, baba[i * 2], baba[i * 2 + 1]);
if (disbaba <= 10*10) {
getbaba = true;
break;
}
}
如果我們用剛剛的distance 作法二,只比較dis * dis 一定沒問題
neoj 4328
Thinking
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
Thinking
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
Thinking
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
| path | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 0 | 7 | 8 | 6 | 3 | 5 | 2 |
解法
int visited[100000] : visited[i] 紀錄走到第 i 位置的人,若從沒被走到過則設為 -1。
int path [n] : 如題目定義,魔法陣列。
int pos : 如題目定義,紀錄每個人當前回合的位置。
- 模擬每回合,一回合移動每個人
- 一個人在移動之後,先檢查新位置有沒有被別人踩過,而且不是自己。
- 如果被別人踩過,return 當前回合數
- 如果沒有,將visited設成自己
解法
int walkOnMyOwnPath(int path[], int pos[], int size, int time){
/* 初始化自己來,小心有沒有人一開始就踩在同個位置上 */
/* visited[i] 初始化為全部都為 -1*/
/* 一開始所有人站的位置,visited[pos[j]]都要設成站在那個位置上的人的index*/
int t = 0;
while(t <= time) {
t++;
for (int j = 0; j < size; j++) {
pos[j] = path[ pos[j] ];
if (visited[pos[j]] != j) {
if(visited[pos[j]] != -1)
return t;
else{
visited[pos[j]] = j;
}
}
}
}
return -1;
}解法
時間複雜度 ?
while(t <= time) {
t++;
for (int j = 0; j < size; j++) {
pos[j] = path[ pos[j] ];
if (visited[pos[j]] != j) {
if(visited[pos[j]] != -1)
return t;
else{
visited[pos[j]] = j;
}
}
}
}
O(10^5 \times 10) \text{?}
如果有人會踩到
一定在100000回合內踩到
解法
時間複雜度 ?
int t = 0;
while(t <= time) {
t++;
for (int j = 0; j < size; j++) {
pos[j] = path[ pos[j] ];
if (visited[pos[j]] != j) {
if(visited[pos[j]] != -1)
return t;
else{
visited[pos[j]] = j;
}
}
}
}
O(10^9 \times 10) \text{?}
要是一直循環??
解法
時間複雜度 ? 修正 ?
bool circle = false;
int t = 0;
while(!circle && t <= time) {
t++;
circle = true;
for (int j = 0; j < size; j++) {
pos[j] = path[ pos[j] ];
if (visited[pos[j]] != j) {
if(visited[pos[j]] != -1)
return t;
else{
visited[pos[j]] = j;
circle = false;
}
}
}
}O(10^5 \times 10) \text{?}
判斷出現了cycle !?!?!?!?
2022竹區C班4/16作業講解
By tunchin kao
2022竹區C班4/16作業講解
- 124