有个2*N+1的线性的棋盘,开始时最左边全是白,右边全是黑,中间一个空格。目标是黑白全部互换。求输出最少步数的操作的棋子的下标。并且要字典序最小的。
980ms险过。
不判重700ms能过。我居然多此一举的用map判重。
/*
ID: modengd1
PROG: shuttle
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <vector>
#include <memory.h>
#include <map>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
map<string,bool> vis;
struct node
{
string sta;
string ans;
};
void output(string S)
{
for(int i=0;i<S.size();i++)
{
if((i%20)==0&&i>0)
cout<<endl;
if((i%20)==0)
printf("%d",S[i]-'0');
else
printf(" %d",S[i]-'0');
}
cout<<endl;
}
int main()
{
freopen("shuttle.in","r",stdin);
freopen("shuttle.out","w",stdout);
int N;
string start,target;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
start.push_back('W');
target.push_back('B');
}
start.push_back(' ');
target.push_back(' ');
for(int i=0;i<N;i++)
{
start.push_back('B');
target.push_back('W');
}
N=2*N+1;
queue<node> Q;
Q.push(node{start,""});
while(!Q.empty())
{
node now=Q.front();Q.pop();
if(now.sta==target)
{
output(now.ans);
return 0;
}
for(int i=0;i<N;i++)
{
node next=now;
if(now.sta[i]=='W'&&now.sta[i+1]==' '&&i<N-1)
{
next.sta[i+1]='W';
next.sta[i]=' ';
next.ans.push_back(i+'1');
if(!vis[next.sta])
Q.push(next);
vis[next.sta]=true;
}
else if(now.sta[i]=='W'&&now.sta[i+1]=='B'&&now.sta[i+2]==' '&&i<N-2)
{
next.sta[i+2]='W';
next.sta[i]=' ';
next.ans.push_back(i+'1');
if(!vis[next.sta])
Q.push(next);
vis[next.sta]=true;
}
else if(now.sta[i]==' '&&now.sta[i+1]=='B'&&i<N-1)
{
next.sta[i+1]=' ';
next.sta[i]='B';
next.ans.push_back(i+1+'1');
if(!vis[next.sta])
Q.push(next);
vis[next.sta]=true;
}
else if(now.sta[i]==' '&&now.sta[i+1]=='W'&&now.sta[i+2]=='B'&&i<N-2)
{
next.sta[i+2]=' ';
next.sta[i]='B';
next.ans.push_back(i+2+'1');
if(!vis[next.sta])
Q.push(next);
vis[next.sta]=true;
}
}
}
return 0;
}