题目链接:here
题意:
给你四个数字,每次可以将其中任何一个数字 +1 或者 -1 ; 1的时候-1 等于9 ;9的时候+1 等于1; 问最少需要变换几次,才可以变到目标序列。。
分析:
我先用广搜做了一遍,随后又用双向广搜做了一遍,发现双向广搜效率的确很高!
贴一下图:
第一个是双向广搜的,下面的是广搜。。。
晒代码:
广搜:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
struct node
{
int num[4];
int step;
};
queue<node> q;
bool vis[10][10][10][10];
int ansnum[4];
int ans;
int dir[8][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1},{-1,0,0,0},{0,-1,0,0},{0,0,-1,0},{0,0,0,-1}};
void init()
{
memset(vis, false, sizeof(vis));
while (!q.empty()) q.pop();
}
bool istrue(node x)
{
if (x.num[0] == ansnum[0] && x.num[1] == ansnum[1] && x.num[2] == ansnum[2] && x.num[3] == ansnum[3])
return true;
return false;
}
bool judge(node x)
{
if (vis[x.num[0]][x.num[1]][x.num[2]][x.num[3]]) return false;
return true;
}
node change(node a, int b)
{
a.step ++;
if (b < 4) // +
{
if (a.num[b] == 9) a.num[b] = 1;
else a.num[b] ++;
}
else if (b < 8) // -
{
if (a.num[b%4] == 1) a.num[b%4] = 9;
else a.num[b%4] = a.num[b%4] - 1;
}
else // 换
{
int tmp;
b %= 4;
tmp = a.num[b];
a.num[b] = a.num[b+1];
a.num[b+1] = tmp;
}
return a;
}
void bfs()
{
node now, next;
while (!q.empty())
{
now = q.front();
q.pop();
if (istrue(now))
{
ans = now.step;
return ;
}
for (int i = 0; i < 11; i++)
{
next = change(now, i);
if (judge(next))
{
vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = true;
q.push(next);
}
}
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
init();
int a, b;
node now;
scanf("%d %d", &a, &b);
for (int i=3; i>=0; i--)
{
ansnum[i] = a % 10;
now.num[i] = b % 10;
a /= 10;
b /= 10;
}
now.step = 0;
q.push(now);
vis[now.num[0]][now.num[1]][now.num[2]][now.num[3]] = true;
bfs();
printf("%d\n", ans);
}
return 0;
}
双向广搜:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
struct node
{
int num[4];
int step;
};
queue<node> q[2];
int vis[2][10][10][10][10];
int ansnum[4];
int ans;
void init()
{
ans = -1;
memset(vis, -1, sizeof(vis));
while (!q[0].empty()) q[0].pop();
while (!q[1].empty()) q[1].pop();
}
bool istrue(node x, int i)
{
if (vis[1^i][x.num[0]][x.num[1]][x.num[2]][x.num[3]] != -1)
return true;
return false;
}
bool judge(node x, int i)
{
if (vis[i][x.num[0]][x.num[1]][x.num[2]][x.num[3]] != -1) return false;
return true;
}
node change(node a, int b)
{
a.step ++;
if (b < 4) // +
{
if (a.num[b] == 9) a.num[b] = 1;
else a.num[b] ++;
}
else if (b < 8) // -
{
if (a.num[b%4] == 1) a.num[b%4] = 9;
else a.num[b%4] = a.num[b%4] - 1;
}
else // 换
{
int tmp;
b %= 4;
tmp = a.num[b];
a.num[b] = a.num[b+1];
a.num[b+1] = tmp;
}
return a;
}
void bfs(int j)
{
node now, next;
if (ans != -1 || q[j].empty()) return ;
int first = q[j].front().step;
while (!q[j].empty() && q[j].front().step == first)
{
now = q[j].front();
q[j].pop();
if (istrue(now, j))
{
ans = vis[j][now.num[0]][now.num[1]][now.num[2]][now.num[3]] + vis[1^j][now.num[0]][now.num[1]][now.num[2]][now.num[3]];
return ;
}
for (int i = 0; i < 11; i++)
{
next = change(now, i);
if (judge(next, j))
{
vis[j][next.num[0]][next.num[1]][next.num[2]][next.num[3]] = next.step;
q[j].push(next);
}
}
}
}
void db_bfs()
{
while (ans == -1)
{
bfs(0);
bfs(1);
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
init();
int a, b;
node now0, now1;
scanf("%d %d", &a, &b);
for (int i=3; i>=0; i--)
{
now0.num[i] = a % 10;
now1.num[i] = b % 10;
a /= 10;
b /= 10;
}
now0.step = 0;
q[0].push(now0);
vis[0][now0.num[0]][now0.num[1]][now0.num[2]][now0.num[3]] = 0;
now1.step = 0;
q[1].push(now1);
vis[1][now1.num[0]][now1.num[1]][now1.num[2]][now1.num[3]] = 0;
db_bfs();
printf("%d\n", ans);
}
return 0;
}