SPOJ KATHTHI - KATHTHI

以前并不知道这个trick。

$01BFS$,在$bfs$的时候用一个双端队列来维护,如果边权为$1$就添加到队尾,边权为$0$就添加到队首。

还有一个小trick就是我们可以开一个$dis$数组来代替$vis$数组做类似于$dp$的操作,因为双端插入的特性使$vis$的表示可能产生歧义,每一次能更新$dis$即入队,这样子也刚好对应了最短路的意义。

时间复杂度$O(Tn^2)$。

Code:

#include <cstdio>
#include <cstring>
#include <deque>
using namespace std;

const int N = 1005;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

int testCase, n, m, dis[N][N];
char mp[N][N];

struct Node {
    int x, y, stp;

    inline Node(int nowX = 0, int nowY = 0, int nowStp = 0) {
        x = nowX, y = nowY, stp = nowStp;
    }

};
deque <Node> Q;

inline bool valid(Node now) {
    return now.x >= 1 && now.x <= n && now.y >= 1 && now.y <= m;
}

int bfs() {    
    if(n == 1 && m == 1) return 0;
    memset(dis, 0x3f, sizeof(dis));
    dis[1][1] = 0;
    Q.clear();    

    Q.push_back(Node(1, 1, 0));
    for(; !Q.empty(); ) {
        Node out = Q.front(); Q.pop_front();
        for(int i = 0; i < 4; i++) {
            Node in = Node(out.x + dx[i], out.y + dy[i], 0);
            if(!valid(in)) continue;
            if(dis[in.x][in.y] <= dis[out.x][out.y] + (mp[out.x][out.y] != mp[in.x][in.y]))
                continue;
            dis[in.x][in.y] = dis[out.x][out.y] + (mp[out.x][out.y] != mp[in.x][in.y]);
            in.stp = dis[in.x][in.y];
            if(in.stp == out.stp) Q.push_front(in);
            else Q.push_back(in);
        }
    }
}

int main() {
    for(scanf("%d", &testCase); testCase--; ) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) scanf("%s", mp[i] + 1);
        bfs();
        printf("%d\n", dis[n][m]);

/*        for(int i = 1; i <= n; i++, printf("\n"))
            for(int j = 1; j <= m; j++)
                printf("%c ", mp[i][j]);
        
        printf("\n");
        for(int i = 1; i <= n; i++, printf("\n"))
            for(int j = 1; j <= m; j++)
                printf("%d ", vis[i][j]);    */

    }
    return 0;
}
View Code

 

posted @ 2018-10-16 13:25  CzxingcHen  阅读(197)  评论(0编辑  收藏  举报