NC51032 八数码问题
题目链接
关键点:
1、题目要求求出每次的方向,我们用一个map来使每一次形成的字串和数字一一对应,用一个last数组来存上次字串的数字,用一个字符串数组来使数字和字串连接,用一个队列来存当前的字串对应的数字,然后进行bfs
2、如何输出,利用dfs last数组,找到最原先的字串然后倒着输出方向
# include <bits/stdc++.h>
using namespace std;
const int N = 362900;
string tar = "12345678x";
map<string, int>mp;
string s[N];
int last[N];
char d[N];
int X[5] = {0, 0, 1, -1};
int Y[5] = {1, -1, 0, 0};
char dir[5] = {'r', 'l', 'd', 'u'};
queue<int>q;
bool bfs(string st)
{
int cnt = 1;
mp[st] = 1;
s[1] = st;
q.push(1);
while (!q.empty())
{
int t = q.front();
string x = s[q.front()];
q.pop();
int pos = x.find('x');
int x1 = pos/3;
int y1 = pos%3;
for (int i=0; i<4; i++)
{
int x2 = x1+X[i];
int y2 = y1+Y[i];
if (x2<0||x2>=3||y2<0||y2>=3)
continue;
string tmp = x;
swap(tmp[pos], tmp[x2*3+y2]);
if (mp.find(tmp) != mp.end()) continue;
mp[tmp] = ++cnt;
last[cnt] = t;
s[cnt] = tmp;
d[cnt] = dir[i];
if (tmp == tar)
return true;
q.push(cnt);
}
}
return false;
}
void find(int x)
{
if (last[x])
{
find(last[x]);
cout<<d[x];
}
}
int main()
{
string st;
for (int i=0; i<9; i++)
{
char a;
cin>>a;
st+=a;
}
if (bfs(st))
find(mp[tar]);
else
cout<<"unsolvable"<<endl;
return 0;
}
NC16742 字串变换
题目链接
关键点:
1、更为复杂,因为数据原因,我们需要进行双向广搜,对A变成B的5步过程,和B变成A的5步过程,然后看其中是否有相交的部分
# include <bits/stdc++.h>
using namespace std;
int disA[1000000], disB[1000000];
string a[10], b[10];
map<string, int>mp;
string A, B;
vector<string>ve;
queue<int>q;
int n;
int cnt = -1;
int bfs(string s, int dis[], string a[], string b[])
{
while (!q.empty()) q.pop();
mp[s] = ++cnt;
ve.push_back(s);
dis[cnt] = 0;
q.push(cnt);
while (!q.empty())
{
int tmp = q.front();
q.pop();
if (dis[tmp] == 5) return 0;
string cur = ve[tmp];
int l = cur.length();
for (int i=1; i<=n; i++)
{
for (int j=0; j<l;)
{
string nxt = cur;
int pos = nxt.find(a[i], j);
if (pos == string::npos) break;
j = pos+1;
nxt.erase(pos, a[i].length());
nxt.insert(pos, b[i]);
if (mp.find(nxt) == mp.end())
{
mp[nxt] = ++cnt;
dis[cnt] = dis[tmp]+1;
ve.push_back(nxt);
if (nxt == B) return 1;
q.push(cnt);
}
else if (dis[mp[nxt]] == -1)
{
dis[mp[nxt]] = dis[tmp]+1;
if (nxt == B) return 1;
q.push(cnt);
}
}
}
}
return 0;
}
int main()
{
cin>>A>>B;
n = 1;
while (cin>>a[n]>>b[n]) n++;
memset(disA, -1, sizeof(disA));
memset(disB, -1, sizeof(disB));
if (bfs(A, disA, a, b))
{
cout<<disA[mp[B]];
return 0;
}
bfs(B, disB, b, a);
int ans = 10000;
for (int i=0; i<=cnt; i++)
{
if (disA[i] != -1 && disB[i] != -1)
ans = min(ans, disA[i]+disB[i]);
}
if (ans>10) cout<<"NO ANSWER!"<<endl;
else
cout<<ans;
return 0;
}