poj1184 聰明的打字員 BFS+剪枝

思路:題意很直觀,用密碼、光標位置來表示二維狀態,對光標所在位置分別進行六種操作,得到新狀態入隊。但一共有1000000*6種狀態,所以需要剪枝。

由於swap0和swap1這兩個交換操作只對光標處和0, 5位置的數字有效,當光標在j處時(0<j<5),若與目標狀態的j位不一樣,則使用left和right會失去修改第j位的機會(光標已不在此處,既不能swap也不能直接修改),只有當光標再次回到j時,纔可向目標狀態修改。故這種情況下使用left和right不是最優的。只有當前狀態的j位與目標狀態的j位相同時,才能使用left和right。

代碼如下:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define N 1000005
#define M 7
#define UP 1
#define DOWN -1
char a[M], b[M];
int factor[M], num[6];
bool vis[N][6];
struct Node{
    int val, idx, step;
    Node(int v, int i, int s): val(v), idx(i), step(s) {}
};

int get_hash(char s[M]){
    int res = 0;
    for(int i = 0; i < 6; ++i)
        res = s[i] - '0' + res * 10;
    return res;
}

inline int swap(int num, int idx1, int idx2){
	int v1 = (num / factor[idx1]) % 10;
	int v2 = (num / factor[idx2]) % 10;
	num += (v2 - v1) * factor[idx1];
	num += (v1 - v2) * factor[idx2];
	return num;
}

inline int up_down(int num, int idx, int ops){
    return num + ops * factor[idx];
}

int bfs(int orig, int dest){
	memset(vis, false, sizeof(vis));
	queue<Node> qu;
	qu.push(Node(orig, 0, 0));
	vis[orig][0] = true;
	while(!qu.empty()){
        Node cur = qu.front();
        qu.pop();
        int sta = cur.val, idx = cur.idx, step = cur.step;
        if(sta == dest)
            return step;
        ++step;
        if(idx != 0){ //swap0
            int next = swap(sta, 0, idx);
            if(!vis[next][idx])
                qu.push(Node(next, idx, step)), vis[next][idx] = true;
        }
        if(idx != 5){ //swap1
            int next = swap(sta, 5, idx);
            if(!vis[next][idx])
                qu.push(Node(next, idx, step)), vis[next][idx] = true;
        }
        int val = (sta / factor[idx]) % 10;
        if(val != 9 && val != num[idx]){ //up
            int next = up_down(sta, idx, UP);
            if(!vis[next][idx])
                 qu.push(Node(next, idx, step)), vis[next][idx] = true;
        }
        if(val != 0 && val != num[idx]){ //down
            int next = up_down(sta, idx, DOWN);
            if(!vis[next][idx])
                 qu.push(Node(next, idx, step)), vis[next][idx] = true;
        }
        if(idx != 0 && (idx == 5 || val == num[idx])){ //left
            if(!vis[sta][idx - 1])
                qu.push(Node(sta, idx - 1, step)), vis[sta][idx - 1] = true;
        }
        if(idx != 5 && (idx == 0 || val == num[idx])){ //right
            if(!vis[sta][idx + 1])
                qu.push(Node(sta, idx + 1, step)), vis[sta][idx + 1] = true;
        }
	}
 	return -1;
}

int main(){
    factor[5] = 1;
    for(int i = 4; i >= 0; --i)
        factor[i] = 10 * factor[i + 1];
	scanf("%s %s", a, b);
	for(int i = 0; i < 6; ++i)
		num[i] = b[i] - '0';
	int orig = get_hash(a), dest = get_hash(b);
	printf("%d\n", bfs(orig, dest));
	return 0;
}


發佈了65 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章