第一次使用双向广搜算法求解,感觉效率的确提高了不止两倍。刚开始的一直WA,后来发现是每次都要扩展一层的节点,然后在扩展另一层的节点,而不是每次只扩展一个节点。
struct node {
char digit[5];
int step;
};
int n;
//初始化状态搜索标记数组(标记要达到某种状态需要的步数)
int mark1[11][11][11][11];
//最终状态搜索标记数组(标记要达到某种状态需要的步数)
int mark2[11][11][11][11];
//初始状态
char a[5];
//最终状态
char b[5];
void bbfs() {
int i;
//初始化标记数组
memset(mark1, -1, sizeof(mark1));
memset(mark2, -1, sizeof(mark2));
//广搜使用的队列
queue<node> Q1;
queue<node> Q2;
node cur, q, temp;
strcpy(q.digit, a);
q.step = 0;
Q1.push(q);
strcpy(q.digit, b);
q.step = 0;
Q2.push(q);
int flag = 1;
//用来标记当前的步数
int pre1 = 0;
int pre2 = 0;
while (1) {
//用广度优先扩展一层正向的节点如果发现扩展出来的节点在反向节点中出现则输出结果
while (!Q1.empty() && Q1.front().step == pre1) {
int k;
cur = Q1.front();
Q1.pop();
//如果当前的状态没有被标记,则标记
if (mark1[cur.digit[0] - '0'][cur.digit[1] - '0'][cur.digit[2] - '0'][cur.digit[3] - '0'] == -1)
mark1[cur.digit[0] - '0'][cur.digit[1] - '0'][cur.digit[2] - '0'][cur.digit[3] - '0'] = cur.step;
//扩展出来的节点在反向节点中出现,则输出答案
k = mark2[cur.digit[0] - '0'][cur.digit[1] - '0'][cur.digit[2] - '0'][cur.digit[3] - '0'];
if (k != -1) {
printf("%d/n", cur.step + k);
return;
}
//扩展节点,有三种扩展方式,加一,减一,交换相邻的数
for (i = 0; i < 4; i++) {
//加一
strcpy(temp.digit, cur.digit);
temp.digit[i]++;
if (temp.digit[i] == '9' + 1) {
temp.digit[i] = '1';
}
temp.step = cur.step + 1;
//扩展出来的节点在反向节点中出现,则输出答案
k = mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q1.push(temp);
}
}
//减一
strcpy(temp.digit, cur.digit);
temp.digit[i]--;
if (temp.digit[i] == '0') {
temp.digit[i] = '9';
}
temp.step = cur.step + 1;
//扩展出来的节点在反向节点中出现,则输出答案
k = mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q1.push(temp);
}
}
//交换位置
if (i < 3) {
strcpy(temp.digit, cur.digit);
temp.digit[i] = cur.digit[i + 1];
temp.digit[i + 1] = cur.digit[i];
if (strcmp(temp.digit, cur.digit) != 0) {
temp.step = cur.step + 1;
//扩展出来的节点在反向节点中出现,则输出答案
k = mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q1.push(temp);
}
}
}
}
}
}
pre1 = Q1.front().step;
//用广度优先算法扩展一层反向节点,如果发现扩展出来的节点在正向节点中出现过,则输出结果
while (!Q2.empty() && Q2.front().step == pre2) {
int k;
cur = Q2.front();
Q2.pop();
k = mark1[cur.digit[0] - '0'][cur.digit[1] - '0'][cur.digit[2] - '0'][cur.digit[3] - '0'];
if (k != -1) {
printf("%d/n", cur.step + k);
return;
}
for (i = 0; i < 4; i++) {
//加一
strcpy(temp.digit, cur.digit);
temp.digit[i]++;
if (temp.digit[i] == '9' + 1) {
temp.digit[i] = '1';
}
temp.step = cur.step + 1;
k = mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q2.push(temp);
}
}
//减一
strcpy(temp.digit, cur.digit);
temp.digit[i]--;
if (temp.digit[i] == '0') {
temp.digit[i] = '9';
}
temp.step = cur.step + 1;
k = mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q2.push(temp);
}
}
//交换位置
if (i < 3) {
strcpy(temp.digit, cur.digit);
temp.digit[i] = cur.digit[i + 1];
temp.digit[i + 1] = cur.digit[i];
if (strcmp(temp.digit, cur.digit) != 0) {
temp.step = cur.step + 1;
k = mark1[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'];
if (k != -1) {
printf("%d/n", temp.step + k);
return;
} else {
if (mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] == -1) {
mark2[temp.digit[0] - '0'][temp.digit[1] - '0'][temp.digit[2] - '0'][temp.digit[3] - '0'] = temp.step;
Q2.push(temp);
}
}
}
}
}
}
pre2 = Q2.front().step;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1195.txt", "r", stdin);
#endif
scanf("%d", &n);
while (n--) {
scanf("%s%s", a, b);
bbfs();
}
return 0;
}