抓住那頭牛(POJ3278)
阿新 • • 發佈:2018-11-26
抓住那頭牛(POJ3278)
題目:
https://cn.vjudge.net/problem/POJ-3278
程式碼如下:
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define MAX 1000005 int step[MAX]; bool vis[MAX]; queue<int> q; int bfs(int n,int k) { int head,next; q.push(n); step[n] = 0;//初始位置花費時間0 vis[n] = 0; while(!q.empty()) { head = q.front(); q.pop(); for(int i = 0;i < 3;i++) { if(i == 0) next = head - 1; else if(i == 1) next = head + 1; else if(i == 2) next = head * 2; if(next < 0 || next >= MAX) continue; if(vis[next]) { q.push(next); vis[next] = 0;//變成舊點 step[next] = step[head] + 1;//每走一步花費時間加1 } if(next == k) return step[next];//判斷該點是否為牛的位置 } } } int main() { int n,k; while(~scanf("%d%d",&n,&k)) { memset(step,0,sizeof(step)); memset(vis,1,sizeof(vis)); if(n >= k) cout << n - k << endl; else cout << bfs(n,k) << endl; } return 0; }
廣度優先搜尋(Breadth First Search)過程:
(1) 把初始節點S0放入Open表中;
(2) 如果Open表為空,則問題無解,失敗退出;
(3) 把Open表的第一個節點取出放入 Closed表,並記該節點為n;
(4) 考察節點n是否為目標節點。若是, 則得到問題的解,成功退出;
(5) 若節點n不可擴充套件,則轉第(2)步;
(6) 擴充套件節點n,將其不在Closed表和 Open表中的子節點(判重)放入Open表的尾部 ,併為每一個子節點設定指向父節點的指標( 或記錄節點的層次),然後轉第(2)步。
此題思路:
這道題要分為兩種情況,第一種就是牛在農夫左面(也就是n >= k)這個時候農夫最快的走法只能不停的每次往左邊移動一個,所以直接輸出n - k就是最少時間了。
第二種就是牛在農夫的右側,首先需要把數軸上每個點都初始化為1(也就是每個點都是新點)然後這個時候就要用bfs去求最短時間了。在bfs函式中首先把農夫的起始位置的座標放入佇列中,隨後從佇列中取出該值。然後列舉從這個點走向下一點所有可能的位置,如果這些位置都是新點並且都在範圍中則放入佇列中,然後把這些位置的點都變成舊點。並且走到這些點的時間等於上一個點所花時間加一。做完這些步驟後判斷該點的位置是否為牛的位置,如果是的就返回走到該點所花的時間,否則再接著搜尋。
簡單來說執行bfs是就是先把最初位置放入佇列,然後隊頭出隊,並且把從這個點走到下一個點可能的位置都放入佇列,然後此時再讓隊頭出隊,並把從這個點走到下一個點可能的位置都放入佇列,一直執行這個操作。