原题:
The 8-puzzle is a square tray in which eight square tiles are placed. The remaining ninth square is uncovered. Each tile has a number on it. A tile that is adjacent to the blank space can be slid into that space. A game consists of a starting state and a specified goal state. The starting state can be transformed into the goal state by sliding (moving) the tiles around. The 8-puzzle problem asks you to do the transformation in minimum number of moves.
However, our current problem is a bit different. In this problem, given an initial state of the puzzle your are asked to discover a goal state which is the most distant (in terms of number of moves) of all the states reachable from the given state.
Input
The first line of the input file contains an integer representing the number of test cases to follow. A blank line follows this line. Each test case consists of 3 lines of 3 integers each representing the initial state of the puzzle. The blank space is represented by a ‘0’ (zero). A blank line follows each test case.
Output
For each test case first output the puzzle number. The next 3 lines will contain 3 integers each representing one of the most distant states reachable from the given state. The next line will contain the shortest sequence of moves that will transform the given state to that state. The move is actually the movement of the blank space represented by four directions: ‘U’ (Up), ‘L’ (Left), ‘D’ (Down) and‘R’ (Right).
After each test case output an empty line.
Sample Input
1
2 6 4
1 3 7
0 5 8
Sample Output
Puzzle #1
8 1 5
7 3 6
4 0 2
UURDDRULLURRDLLDRRULULDDRUULDDR
中文:
给你一个八数码的起始状态,然后问你距离这个这个八数码最远的一个状态是什么样?
#include <bits/stdc++.h>
using namespace std;
struct node
{
string st;
vector<char> dir;
};
unordered_map<string,node> ums;
int t;
node Down(node n,int pos)
{
if(pos>=6)
{
n.st="#";
return n;
}
swap(n.st[pos],n.st[pos+3]);
n.dir.push_back('D');
return n;
}
node Up(node n,int pos)
{
if(pos<3)//0在第一行
{
n.st="#";
return n;
}
swap(n.st[pos],n.st[pos-3]);
n.dir.push_back('U');
return n;
}
node Left(node n,int pos)//不能在最右侧
{
if(pos%3==2)
{
n.st="#";
return n;
}
swap(n.st[pos],n.st[pos+1]);
n.dir.push_back('R');
return n;
}
node Right(node n,int pos)
{
if(pos%3==0)
{
n.st="#";
return n;
}
swap(n.st[pos],n.st[pos-1]);
n.dir.push_back('L');
return n;
}
node bfs(node start,string state)
{
queue<node> Q;
Q.push(start);
ums[state]=start;
node ans;
int _max=0;
while(!Q.empty())
{
node head=Q.front();
// cout<<head.st<<endl;
if(head.dir.size()>_max)
// if(head.dir.size()==31)//如果步数等于31就break返回答案
{
ans=head;
// break;
_max=head.dir.size();
}
Q.pop();
int zero=head.st.find('0');
node u=Up(head,zero);
node d=Down(head,zero);
node l=Left(head,zero);
node r=Right(head,zero);
if(u.st!="#")
{
if(ums.find(u.st)==ums.end())
{
ums.insert(make_pair(u.st,u));
Q.push(u);
}
}
if(d.st!="#")
{
if(ums.find(d.st)==ums.end())
{
ums.insert(make_pair(d.st,d));
Q.push(d);
}
}
if(l.st!="#")
{
if(ums.find(l.st)==ums.end())
{
ums.insert(make_pair(l.st,l));
Q.push(l);
}
}
if(r.st!="#")
{
if(ums.find(r.st)==ums.end())
{
ums.insert(make_pair(r.st,r));
Q.push(r);
}
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
int k=1;
while(t--)
{
string st;
node start;
ums.clear();
for(int i=1;i<=9;i++)
{
string s;
cin>>s;
st+=s;
}
start.st=st;
node ans=bfs(start,st);
cout<<"Puzzle #"<<k++<<endl;
for(int i=0;i<ans.st.size();i++)
{
cout<<ans.st[i];
if((i+1)%3==0)
cout<<endl;
else
cout<<" ";
}
// cout<<ans.dir.size()<<endl;
for(auto c:ans.dir)
cout<<c;
cout<<endl;
cout<<endl;
}
return 0;
}
解答:
要找最远的状态,使用广搜,搜索到队列最后一个状态,也就是最远的状态了。可以使用康拓展开或者是哈希函数来实现。
本以为写完代码以后会超时,结果一下题目上的时间要求是13s,晕~
不过,通过自己写了两组数据发现了一个此题的规律!那就是最远状态的路径长度一定是等于31步,但是没有证明,我自己猜的,使用这个结论以后还ac了,又因为八数码问题可以使用启发式搜索来解答,所以我感觉此题绝对可以有很大的优化空间,看了榜单,有很多的0s过的,但是自己还没想出来-_-