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的偏移量在这里也很妙。

posted @ 2020-10-13 19:05  Lvlb2333  阅读(76)  评论(0编辑  收藏  举报