7-11 Saving James Bond - Hard Version (30 分)
原題鏈接:https://pintia.cn/problem-sets/16/problems/673
這道題本質是就是一道BFS,只不過要加上路徑。
開始做的時候比較順利,但是總是有一個測試點沒過去,找了半天還是找不到錯誤。於是google一下,發現是沒仔細看題。
題目中說,當有多條最短路徑時,選擇第一跳最短的。我竟然麼看見(😭😭找了兩個多小時)。處理第一條最短,比較簡單的做法時我們在用BFS,一開始把鱷魚入隊時,就把順序排好,這樣出來的一定是最終的結果。
思路:
在處理能不能在兩個鱷魚之間跳時,一是可以先計算好能不能跳,然後直接在BFS裏用結果。二是在BFS的過程中,判斷能不能跳。
其實我個人比較推薦第二種,沒必要先計算好,現算現用就行。不過如果計算的結構要多次使用的話,保存下來了比較好。
代碼:
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int MAX = 110;
const int INFO = 1000000;
struct Node{
int X,Y;
Node() {} //用來不初始化定義Ver[101]
Node(int _x,int _y) : X(_x),Y(_y) {} //用來提供X和Y的初始值
}Ver[MAX];
int Path[MAX]; //記錄路徑
int N,D;
bool book[MAX]; //記錄是否訪問
int last = -1;
queue<int> q;
bool IsVertexJump(int a,int b){ //能不能從a到b
return (pow(Ver[a].X-Ver[b].X,2) + pow(Ver[a].Y-Ver[b].Y,2) <= pow(D,2));
}
bool IsSave(int a){ //a能不能到岸
return (pow(Ver[a].X,2) <= pow(D,2) || pow(Ver[a].Y,2) <= pow(D,2) || \
pow(100-Ver[a].X,2) <= pow(D,2) || pow(100-Ver[a].Y,2) <= pow(D,2));
}
int IsCenterJump(int a){ //能不能從中心跳出
if(pow(Ver[a].X-50,2) + pow(Ver[a].Y-50,2) <= pow(D + 7.5,2))
return (pow(Ver[a].X-50,2) + pow(Ver[a].Y-50,2));
else
return 0;
}
bool cmp(int x,int y){ //排序的比較函數
return IsCenterJump(x)<IsCenterJump(y);
}
void Save007(){ //無權圖單源最短路
int temp;
int b[MAX]; //用來把第一跳排序
fill(Path, Path+N+1, INFO);
fill(book, book+N+1, false);
Path[0] = -1;
book[0] = true;
if(IsSave(0)){
last = 0;
return;
}
for(int i=1;i<=N;i++){ //對第一跳排序
b[i] = i;
}
sort(b+1,b+N+1,cmp); //why 第二個是N + 1
for(int i=1;i<=N;i++){ //按靠近center的順序,放入queue
if(IsCenterJump(b[i])){
q.push(b[i]);
Path[b[i]] = 0;
book[b[i]] = true;
}
}
while(!q.empty()){
temp = q.front();
q.pop();
if(IsSave(temp)){ //能不能到岸
last = temp;
break;
}
for(int i=1;i<=N;i++){
if(!book[i] && IsVertexJump(temp,i)){
q.push(i);
Path[i] = temp;
book[i] = true; //在入隊時就book
}
}
}
}
int main(){
int x,y;
int a[MAX]; //記錄最短路徑
int count = 0;
Ver[0] = Node(50,50);
scanf("%d%d",&N,&D);
for(int i=1;i<=N;i++){
scanf("%d%d",&x,&y);
Ver[i] = Node(x+50,y+50);
}
Save007();
if(last == -1) printf("0\n");//輸出結果
else {
while(last > 0){
a[count++] = last;
last = Path[last];
}
printf("%d\n",count+1);
for(int i=count-1;i>=0;i--){
printf("%d %d\n",Ver[a[i]].X-50,Ver[a[i]].Y-50);
}
}
system("pause");
return 0;
}