Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

优化编码 + 双向bfs

Posted by fogsail at 2019-07-23 21:27:02 on Problem 3131
//
//  main.cpp
//  POJ3131-4
//
//  Created by zhangmin chen on 2019/7/22.
//  Copyright © 2019 zhangmin chen. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <assert.h>

using namespace std;
typedef long long llong;
typedef set<int>::iterator ssii;

const int HASHSZ = 2000007;
const int maxn = 2000007;

#define Cmp(a, b) memcmp(a, b, sizeof(b))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define _forS(i, l, r) for(set<int>::iterator i = (l); i != (r); i++)
#define _rep(i, l, r) for(int i = (l); i <= (r); i++)
#define _for(i, l, r) for(int i = (l); i < (r); i++)
#define _forDown(i, l, r) for(int i = (l); i >= r; i--)
#define debug_(ch, i) printf(#ch"[%d]: %d\n", i, ch[i])
#define debug_m(mp, p) printf(#mp"[%d]: %d\n", p->first, p->second)
#define debugS(str) cout << "dbg: " << str << endl;
#define debugArr(arr, x, y) _for(i, 0, x) { _for(j, 0, y) printf("%c", arr[i][j]); printf("\n"); }
#define _forPlus(i, l, d, r) for(int i = (l); i + d < (r); i++)

class HASH {
public:
    struct Node {
        int nxt, val;
    } nodes[HASHSZ];
    
    int head[HASHSZ];
    // head store the value of id
    int tot;
    
    void init() {
        Set(head, -1);
        tot = 0;
    }
    
    void insert(int hashV, int val) {
        nodes[tot].val = val;
        nodes[tot].nxt = head[hashV];
        head[hashV] = tot++;
    }
    
    int find(int dta) {
        int hashV = dta % HASHSZ;
        int i;
        for(i = head[hashV]; ~i; i = nodes[i].nxt) {
            int val = nodes[i].val;
            if(val == dta) return i;
        }
        insert(hashV, dta);
        return tot - 1;
    }
};

HASH hashTb;
void initHash() {
    hashTb.init();
}

bool vis1[maxn], vis2[maxn];
void initVis() {
    Set(vis1, 0);
    Set(vis2, 0);
}

class StNode {
public:
    int state;
    int pos;
    int dist;
    
    StNode(int s = 0, int p = 0, int dist = 0) : state(s), pos(p), dist(dist) {}
};

const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
// const int UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3;

/*
 if(top == W && face == R) return 1;
 if(top == W && face == B) return 2;
 if(top == R && face == W) return 3;
 if(top == R && face == B) return 4;
 if(top == B && face == W) return 5;
 if(top == B && face == R) return 6;
 */

// const int Move[0][dir]
// const int Move[1][dir]
// UP LEFT DOWN RIGHT
// Move[1][UP] = (R, W)  Move[1][LEFT] = (B, R) Move[0][DOWN] = (R, W)  Move[0][RIGHT] = (B, R)
// Move[2][UP] = (B, W)  Move[2][LEFT] = (R, B)
// Move[3][UP] = (W, R)  Move[3][LEFT] = (B, W)
// Move[4][UP] = (B, R)  Move[4][LEFT] = (W, B)
// Move[5][UP] = (W, B)  Move[6][LEFT] = (R, W)
// Move[6][UP] = (R, B)  Move[6][LEFT] = (W, R)

const int Move[7][4] = {
    {0, 0, 0, 0},
    {3, 6, 3, 6},
    {5, 4, 5, 4},
    {1, 5, 1, 5},
    {6, 2, 6, 2},
    {2, 3, 2, 3},
    {4, 1, 4, 1}
};
// usage: int newCode = Move[oldCode][dir]

queue<StNode> que1, que2;
char tar[11];
int tep;

void initQue() {
    while(!que1.empty()) que1.pop();
    while(!que2.empty()) que2.pop();
}

int getBit(int state, int k) {
    return ( ( (state >> (3 * k + 2)) & 1 ) << 2 ) |
           ( ( (state >> (3 * k + 1)) & 1 ) << 1 ) |
           ( ( (state >> (3 * k)) & 1 ));
}


void dfs(int d, int state, int tep) {
    if(d == 9) {
        StNode cur(state, tep, 0);
        que2.push(cur);
        
        int dta2 = hashTb.find(state);
        vis2[dta2] = 1;
        return;
    }
    
    if(tar[d] == 'E') {
        dfs(d + 1, state << 3, tep);
        return;
    }
    
    int v1, v2;
    if(tar[d] == 'W') {
        v1 = 1; v2 = 2;
    }
    else if(tar[d] == 'R') {
        v1 = 3; v2 = 4;
    }
    else {
        v1 = 5; v2 = 6;
    }
    
    dfs(d + 1, (state << 3) | v1, tep);
    dfs(d + 1, (state << 3) | v2, tep);
}

// const int UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3;
inline void update(StNode& u, int dir) {
    if(dir == 0) {
        //
        int np = u.pos - 3;
        int bit = getBit(u.state, 8 - np);
        
        int nbit = Move[bit][dir];
        u.state = (u.state ^ ( bit << ((8 - np) * 3) )) | ( nbit << ((8 - np - 3) * 3) );
        u.dist++;
        u.pos = np;
    }
    else if(dir == 1) {
        int np = u.pos - 1;
        int bit = getBit(u.state, 8 - np);
        
        int nbit = Move[bit][dir];
        u.state = (u.state ^ ( bit << ((8 - np) * 3) )) | ( nbit << ((8 - np - 1) * 3) );
        u.dist++;
        u.pos = np;
    }
    else if(dir == 2) {
        int np = u.pos + 3;
        int bit = getBit(u.state, 8 - np);
        
        int nbit = Move[bit][dir];
        u.state = (u.state ^ ( bit << ((8 - np) * 3) )) | ( nbit << ((8 - np + 3) * 3) );
        u.dist++;
        u.pos = np;
    }
    else if(dir == 3) {
        int np = u.pos + 1;
        int bit = getBit(u.state, 8 - np);
        
        int nbit = Move[bit][dir];
        u.state = (u.state ^ ( bit << ((8 - np) * 3) )) | ( nbit << ((8 - np + 1) * 3) );
        u.dist++;
        u.pos = np;
    }
}

bool valid(int x, int y) {
    if(0 <= x && x < 3 && 0 <= y && y < 3) return true;
    return false;
}

int bfs() {
    const int DEP1 = 20, DEP2 = 9;
    int lv1 = 0, lv2 = 0;
    
    for(lv1 = 0; lv1 <= DEP1; lv1++) {
        while (!que1.empty() && que1.front().dist == lv1) {
            // do something
            StNode x = que1.front(); que1.pop();
            int ex = x.pos / 3, ey = x.pos % 3;
            _for(dir, 0, 4) {
                int nx = ex + dx[dir], ny = ey + dy[dir];
                if(!valid(nx, ny)) continue;
                
                StNode clone = x;
                update(clone, dir);
                int hashV = hashTb.find(clone.state);
                
                if(!vis1[hashV]) {
                    vis1[hashV] = true;
                    if(vis2[hashV]) return lv1 + lv2 + 1;
                    que1.push(clone);
                }
            }
        }
        
        while(!que2.empty() && que2.front().dist == lv2 && lv2 < DEP2) {
            // do something
            StNode x = que2.front(); que2.pop();
            int ex = x.pos / 3, ey = x.pos % 3;
            _for(dir, 0, 4) {
                int nx = ex + dx[dir], ny = ey + dy[dir];
                if(!valid(nx, ny)) continue;
                
                StNode clone = x;
                update(clone, dir);
                int hashV = hashTb.find(clone.state);
                
                if(!vis2[hashV]) {
                    vis2[hashV] = true;
                    if(vis1[hashV]) return lv1 + lv2 + 2;
                    que2.push(clone);
                }
            }
        }
        
        if(lv2 < DEP2) lv2++;
    }
    return -1;
}


int main() {
    //freopen("input.txt", "r", stdin);
    
    int ex, ey;
    while (scanf("%d%d", &ex, &ey) != EOF && ex && ey) {
        initVis();
        initQue();
        initHash();
        ex--; ey--;
        int ep = ey * 3 + ex;
        
        StNode s(0, ep, 0);
        _for(i, 0, 9) {
            s.state <<= 3;
            if(i == ep) continue;
            s.state |= 1;
        }
        que1.push(s);
        
        int dta1 = hashTb.find(s.state);
        vis1[dta1] = 1;
        // get start state finished
        
        
        // then get end status
        char c[3];
        _for(i, 0, 3) _for(j, 0, 3) {
            scanf("%s", c);
            tar[i * 3 + j] = c[0];
            if(c[0] == 'E') tep = i * 3 + j;
        }
        
        // judge 0
        int i;
        for(i = 0; i < 9; i++) {
            if(tar[i] == 'W' && i != s.pos) continue;
            if(tar[i] == 'E' && i == s.pos) continue;
            else break;
        }
        if(i == 9) {
            printf("0\n");
            continue;
        }
        
        // then add all 256 situation to the end queue
        dfs(0, 0, tep);
        // printf("%d\n", que2.size());
        
        // then double-way bfs
        printf("%d\n", bfs());
    }
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator