1. 程式人生 > 實用技巧 >luoguP1443馬的遍歷

luoguP1443馬的遍歷

題目連結

本題主要思路是搜尋

剛開始想寫bfs,寫著寫著就寫假了寫成了dfs

dfs會TLE成80分

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 410;

int n, m;
int ans[N][N];
bool book[N][N];
int dx[8] = {2, 1, 1, 2, -1, -1, -2, -2};
int dy[8] = {1, -2, 2, -1, 2, -2, 1, -1};

void bfs(int x, int y, int d) {
    if(x < 1 || y < 1 || x > n || y > m || (ans[x][y] != -1 && ans[x][y] <= d)) return;
    // q.push({x, y});
    book[x][y] = 1;
    if(ans[x][y] != -1)ans[x][y] = min(ans[x][y], d);
    else ans[x][y] = d;
    for(int i = 0 ; i < 8 ; i ++) {
        bfs(x + dx[i], y + dy[i], d + 1);
    }
    return;
}
void print() {
    for(int i = 1; i <= n ; i ++) {
        for(int j = 1; j <= m ; j ++) {
            printf("%-5d", ans[i][j]);
        }
        printf("\n");
    }
}

int main () {
    int a, b;
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 1; i <= n ; i ++) {
        for(int j = 1; j <= m ; j ++) {
            ans[i][j] = -1;
        } 
    }
    bfs(a, b, 0);
    print();
    return 0;
}

而且這個裡面的book陣列沒有用到


值得一提的是:這道題的輸入輸出非常重要

題目要求左對齊,寬五格

我:printf("%d(+五個空格)", ...); --> 0分

看了看題目是四個空格,於是把五個空格改成了四個空格,20分。

看了題解是printf("%-5d", ...); 80分。(以前wa的點全都ac,剩下的就是tle了)

真就離譜。


接下來開始想正解

bfs,肯定要用到佇列。

  • 先將出初始狀態入隊,列舉這個狀態所有可能的狀態,修改答案。

  • 將當前狀態出隊,列舉到的可能狀態入隊,然後繼續列舉接下來的狀態。

  • 如果列舉到了一個狀態,我們先前已經列舉過了,現在就不用枚舉了,直接continue

    即可。因為原來列舉到過肯定是之前已經走到過,如果再列舉他,標記的值肯定沒有先前的值優,所以不必列舉。
    這也是廣度優先搜尋(寬搜bfs)的一條重要性質

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 410;

int n, m;
int ans[N][N];
bool book[N][N];
int dx[8] = {2, 1, 1, 2, -1, -1, -2, -2};
int dy[8] = {1, -2, 2, -1, 2, -2, 1, -1};

typedef pair<int, int> PII;
void bfs(int x, int y, int d) {
    ans[x][y] = d;
    book[x][y] = 1;
    queue<PII> q;
    q.push({x, y});
    while(q.size()) {
        PII top = q.front();
        q.pop();
        int fx = top.first, fy = top.second;
        for(int i = 0 ; i < 8 ; i ++) {
            int nx = fx + dx[i], ny = fy + dy[i];
            if(nx < 1 || ny < 1 || nx > n || ny > m || book[nx][ny]) continue;
            top.first = nx, top.second = ny;
            q.push(top);
            book[nx][ny] = 1;
            ans[nx][ny] = ans[fx][fy] + 1;
        }
    }
}
void print() {
    for(int i = 1; i <= n ; i ++) {
        for(int j = 1; j <= m ; j ++) {
            printf("%-5d", ans[i][j]);
        }
        printf("\n");
    }
}

int main () {
    int a, b;
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 1; i <= n ; i ++) {
        for(int j = 1; j <= m ; j ++) {
            ans[i][j] = -1;
        } 
    }
    bfs(a, b, 0);
    print();
    return 0;
}

AC程式碼簡單易懂。

dx,dy的偏移量在這裡也很妙。