Knight Moves(信息学奥赛一本通-T1450)
生活随笔
收集整理的這篇文章主要介紹了
Knight Moves(信息学奥赛一本通-T1450)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【題目描述】
編寫一個程序,計算一個騎士從棋盤上的一個格子到另一個格子所需的最小步數。騎士一步可以移動到的位置由下圖給出。
【輸入】
第一行給出騎士的數量 n。
在接下來的 3n 行中,每 3 行描述了一個騎士。其中,第一行一個整數 L 表示棋盤的大小,整個棋盤大小為 L×L;
第二行和第三行分別包含一對整數 (x,y),表示騎士的起始點和終點。假設對于每一個騎士,起始點和終點均合理。
【輸出】
對每一個騎士,輸出一行一個整數表示需要移動的最小步數。如果起始點和終點相同,則輸出 0
【輸入樣例】
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
【輸出樣例】
5
28
0
思路:
BFS 板子題,與 Knight Moves(信息學奧賽一本通-T1257)一個題
下面給出一種 BFS 的優化做法,可以極大加快搜索速度,即:雙向BFS
設置兩個隊列 posQ 和 negQ,分別代表從起點開始搜索的隊列和從終點開始搜索的隊列
對于判重數組 vis[i][j],我們設置三個狀態:未被訪問時為 0,正向搜索到時設為 1,逆向搜索到時設為 2
這樣一來,當正向搜索到 vis[i][j]=2 或逆向搜索到 vis[i][j]=1 時,說明終點起點相遇,此時記錄兩者步數輸出即可
此時的步數即為相遇時起點到該點的距離 dis[nx][ny]+dis[x][y]+1
【源程序】
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long #define Pair pair<int,int> LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; } LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;} LL quickMultPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;} LL quickPowMod(LL a,LL b,LL mod){ LL res=1; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1; } return res; } LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); } LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); } LL LCM(LL x,LL y){ return x/GCD(x,y)*y; } const double EPS = 1E-6; const int MOD = 1000000000+7; const int N = 1000+5; const int dnewStr[] = {0,0,-1,1,1,-1,1,1}; const int dy[] = {1,-1,0,0,-1,1,-1,1}; using namespace std;struct Node {int x, y;Node() {}Node(int x, int y) : x(x), y(y) {} }; int n; int vis[N][N]; int dis[N][N]; int dir[8][2] = {{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}}; void BFS(Node st, Node ed) {if (st.x == ed.x && st.y == ed.y) {printf("0\n");return;}memset(dis, 0, sizeof(dis));memset(vis, 0, sizeof(vis));queue<Node> posQ; //正向隊列queue<Node> negQ; //反向隊列posQ.push(st);negQ.push(ed);vis[st.x][st.y] = 1;vis[ed.x][ed.y] = 2;while (!posQ.empty() || !negQ.empty()) {if (!posQ.empty()) {Node now = posQ.front();posQ.pop();int x = now.x;int y = now.y;for (int i = 0; i < 8; i++) {int nx = x + dir[i][0];int ny = y + dir[i][1];if (nx < 0 || ny < 0 || nx >= n || ny >= n)continue;if (vis[nx][ny] == 2) { //相遇int step = dis[x][y] + dis[nx][ny] + 1;printf("%d\n", step);return;} if (vis[nx][ny] == 0) {vis[nx][ny] = 1;dis[nx][ny] = dis[x][y] + 1;posQ.push(Node(nx, ny));}}}if (!negQ.empty()) {Node now = negQ.front();int x = now.x;int y = now.y;for (int i = 0; i < 8; i++) {int nx = now.x + dir[i][0];int ny = now.y + dir[i][1];if (nx < 0 || ny < 0 || nx >= n || ny >= n)continue;if (vis[nx][ny] == 1) { //相遇int step = dis[nx][ny] + dis[x][y] + 1;printf("%d\n", step);return;} if (vis[nx][ny] == 0) {vis[nx][ny] = 2;dis[nx][ny] = dis[x][y] + 1;negQ.push(Node(nx, ny));}}}} } int main() {int t;scanf("%d", &t);while (t--) {scanf("%d", &n);Node st, ed;scanf("%d%d%d%d", &st.x, &st.y, &ed.x, &ed.y);BFS(st, ed);}return 0; }?
總結
以上是生活随笔為你收集整理的Knight Moves(信息学奥赛一本通-T1450)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通(1019:浮点数向零舍
- 下一篇: 字符串处理 —— 回文串相关 —— 求最