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;
}


你可能感兴趣的:(图论,bfs)