Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3409 | Accepted: 705 |
Description
Input
Output
Sample Input
123456 654321
Sample Output
11
#include
#include
#include
#include
#include
using namespace std;
const int _max=1000001;
int pre,end;//初始状态和目标状态,用整形保存
int fin[6];//目标状态,用数组保存
bool vis[_max][10];//最多有不超过_max个节点,光标最多有10种状态
struct Node
{
int state;//当前状态,用整形保存
int step;//当前步骤
int visited;//0-9
/*
0:0 通过right操作或者是swap0操作,但是光标停留在最后一个元素,没有执行swap1操作
1:0, 1
2:0, 1, 2
3:0, 1, 2, 3
4:0, 1, 2, 3, 4
5:0, 5 通过swap1操作,但是光标还是停留在i-5处
6:0, 1, 5
7:0, 1, 2, 5
8:0, 1, 2, 3, 5
9:0, 1, 2, 3, 4, 5
*/
// 不需要考虑left操作,因为没有意义
};
int abss(int x) {return x>0?x:-x;}
void toarray(int n,int *a)//将整数保存到数组中
{
for(int i=5;i>=0;i--)
{
a[i]=n%10;
n/=10;
}
}
int tonum(int *a)//将数组转化成整数形式
{
int cnt=0;
for(int i=0;i<6;i++) cnt=cnt*10+a[i];
return cnt;
}
int swapnum(int n,int m,int *a)//返回a[n]和a[m]交换后的状态,但是并不真的交换
{
swap(a[n],a[m]);
int cnt=tonum(a);
swap(a[n],a[m]);//复位
return cnt;
}
int check(const Node& temp)//检查当前状态是否和目标状态相同(这里只比较光标尚未走过的区域),返回-1表示不相同
{
int a[6];
toarray(temp.state,a);//将此时状态保存到a数组中,便于和目标状态比较
int tmp=temp.visited;//当天光标遍历过的位置
int cnt=0;//保存和目标状态相差的步数(只用up和down操作)
if(tmp<=4) //尚未执行swap1操作,光标只是右移或者是执行swap0操作
{
for(int i=tmp+1;i<6;i++)// 需要比较到最后一个
{
if(a[i]!=fin[i]) return -1;//和目标状态不同
}
for(int i=0;i<=tmp;i++) cnt+=abss(a[i]-fin[i]);//通过up和down操作
}
else //已经执行过了swap1操作,但是光标还是停留在tmp-5处
{
tmp-=5;//当天光标位置
for(int i=tmp+1;i<5;i++)// 只需比较到第5个
{
if(a[i]!=fin[i]) return -1;//和目标状态不同
}
for(int i=0;i<=tmp;i++) cnt+=abss(a[i]-fin[i]);//通过up和down操作
cnt+=abss(a[5]-fin[5]);
}
return cnt;
}
queueq;
int bfs()
{
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
int _min=_max;//最小步数
Node st;
st.state=pre,st.step=0,st.visited=0;//初始化
vis[pre][0]=1;
q.push(st);
while(!q.empty())
{
Node p=q.front();q.pop();
int ori=p.state,visited=p.visited;//保存数据,防止下面操作将其值覆盖
int res=check(p);//表示和目标状态还差多少步,-1表示和目标状态不相同
if(res!=-1)
{
if(p.step+res<_min) _min=p.step+res;//到目标状态总的步数
}
//拓展节点
p.step++;//步数加1,important 不能在下面加,否则会重复加
if(p.step>=_min) continue;//剪枝
int a[6];
toarray(p.state,a);//保存当前状态
int tmp;//保存执行swap 0后的状态,用整形保存
//swap 0
if(p.visited>0) //如果在0点的话,不用执行swap 0
{
if(p.visited>=5) //已经执行过了swap 1
{
tmp=swapnum(0,p.visited-5,a);
}
else
{
tmp=swapnum(0,p.visited,a);
}
if(!vis[tmp][p.visited])//如果当前状态尚未走过
{
p.state=tmp;
q.push(p);
vis[tmp][p.visited]=1;
}
}
//swap 1
if(p.visited<5) //尚未执行swap 1操作
{
tmp=swapnum(5,p.visited,a);
p.visited+=5;//important
}
else
{
tmp=swapnum(5,p.visited-5,a);
}
if(!vis[tmp][p.visited])
{
p.state=tmp;
//p.visited不用改变
q.push(p);
vis[tmp][p.visited]=1;
}
//right
p.state=ori,p.visited=visited;//恢复数据
if(p.visited<5)
{
p.visited++;
if(!vis[p.state][p.visited]) q.push(p);
}
else if(p.visited<9)
{
p.visited++;
if(!vis[p.state][p.visited]) q.push(p);
}
}
return _min;
}
/*int bfs( )
{
queueq;
Node p;
int ori, visited, tmp, a[ 6 ] , res, _min = _max;
memset ( vis, false , sizeof ( vis) ) ;
p.state = pre;
p.step = 0 ;
p.visited = 0 ;
q.push ( p) ;
vis[ pre] [ 0 ] = true ;
while ( !q.empty ( ) )
{
p = q.front ( ) ;
q.pop ( ) ;
ori = p.state ;
visited = p.visited ;
res = check( p) ;
if ( res != -1 )
{
if ( _min > res + p.step ) _min= p.step + res;
}
p.step ++;
if ( p.step >= _min) continue ;//剪枝
toarray( p.state , a) ;
//swap0
if ( p.visited > 0 )
{
if ( p.visited >= 5 ) tmp = swapnum( 0 , p.visited - 5 , a) ;
else tmp = swapnum( 0 , p.visited , a) ;
if ( !vis[ tmp] [ p.visited ] )
{
p.state = tmp;
q.push ( p) ;
vis[ tmp] [ p.visited ] = true ;
}
}
//swap1
if ( p.visited < 5 )
{
tmp = swapnum( 5 , p.visited , a) ;
p.visited += 5 ;
}
else tmp = swapnum( 5 , p.visited - 5 , a) ;
if ( !vis[ tmp] [ p.visited ] )
{
p.state = tmp;
q.push ( p) ;
vis[ tmp] [ p.visited ] = true ;
}
//right
p.state = ori;
p.visited = visited;
if ( p.visited < 5 )
{
p.visited ++;
if ( !vis[ p.state ] [ p.visited ] ) q.push ( p) ;
}
else if ( p.visited < 9 )
{
p.visited ++;
if ( !vis[ p.state ] [ p.visited ] ) q.push ( p) ;
}
}
return _min;
}*/
int main()
{
while(scanf("%d%d",&pre,&end)==2)
{
toarray(end,fin);
int cnt=bfs();
printf("%d/n",cnt);
}
return 0;
}