hdoj1043,eight

1.首先写一下用广搜预处理得到的。这个方法耗时有点大。但是可以通过。

2.主要用了广搜和倒序输出路径。当然,这里的struct比较特殊。需要好好体会。

3.主要问题是,注意良好的编程习惯。我就是两个变量搞混了,导致一直出错。

4.这里借助广搜,因为广搜搜出来的就是最短的了。而深搜就不行。

5.还有就是康拓序列了。这个需要记住了,觉得用的很多。小心正确的顺序康托序列是0;

6.加入1234,计算4231的康托序列,就是看比第一个4小的数有几个就乘以康拓序列的地4位。这是因为类似排列组合,以1,2,3开头的序列数。后面类似。

/*

content:  hdoj1043,找错版本,找到错误,这是正确的答案。
time   :  2015/09/08
author :  kaka

1.看来路径是反的不仅仅指的是顺序,连方向都是。
2.为什么这样找到的事最短的呢?用的是广搜。这是保证。否则深搜就不行。

*/

#include<queue>
#include<iostream>
#include<string>
using namespace std;
#define MAXN  362885
const int N = 9;
struct point
{
	char map[N];
	int position;
	string step;
};
//记录路径的数列
string inversionPath[MAXN];
//康托序列
int fac[N]={1, 1, 2, 6, 24, 120, 720, 5040, 40320};
//标记是不是这个序列已经有了。
bool visited[MAXN];

//看清楚,这里所有的方向都是反的
const int dir[4][2] = {1,0,0,1,-1,0,0,-1};
const char option[4] = {'u','l','d','r'};
//对特定序列计算康托数
int computeCan(point p);

//广搜
bool bfs();
int cantor(point p)
{
	int result=0;
	for ( int i = 0;i < N; i++ )
	{
		int ans = 0;
		for ( int j = i+1;j < N;j++)
		{
			if(p.map[i]>p.map[j])
				ans++;
		}
		//计算已知序列是总数里的第几个。根据第一个数,第二个一次计算。
		result+=fac[8-i]*ans;
	}
	return result;
}

bool bfs()
{
	queue<point> que;
	point p;
	for ( int i = 0; i < N-1; i++)
	{
		p.map[i] = i+1+'0';
	}
	visited[0]=true;
	p.map[N-1] = 'x';
	p.position = 8;
	p.step ="";
	que.push(p);
	
	while(!que.empty())
	{
		
		point nowPoint = que.front();
		que.pop();
		int num = nowPoint.position;
		for (int i = 0; i < 4; i++)
		{
			int row = num/3+dir[i][0];
			int col = num%3+dir[i][1];
			//if(row>=0&&row<3&&col>=0&&col<3)
			if(row>=0&&row<3&&col>=0&&col<3)
			{
				//换上这个不出现两个x
				//p和nowpoint弄混,以后一定要注意
				//为什么不重载就可以用这种构造函数
				point nextPoint(nowPoint);
		        nextPoint.map[nextPoint.position]=nextPoint.map[row*3+col];
		        nextPoint.position=row*3+col;
		        nextPoint.map[nextPoint.position]='x';
				int cantorTemp = cantor(nextPoint);
				if(visited[cantorTemp])
					continue;
				visited[cantorTemp]=true;
				nextPoint.step+=option[i];
				inversionPath[cantorTemp]=nextPoint.step;
				que.push(nextPoint);
				
			}
		}
	}
	
	return false;
}


int main()
{
	point startPoint;
	int cantorNum;
	bfs();

	while(cin>>startPoint.map[0])
	{
		if(startPoint.map[0]=='x')
			startPoint.position=0;
		for(int i=1;i<9;i++)    
        {  
            cin>>startPoint.map[i];  
            if(startPoint.map[i]=='x')  
                startPoint.position=i;  
        }  

		cantorNum = cantor(startPoint);
		if(visited[cantorNum])
		{
			
			for ( int i = inversionPath[cantorNum].size()-1; i>=0;i--)
				cout << inversionPath[cantorNum][i];
			cout << endl;
		}else {
			 cout<<"unsolvable"<<endl; 
		}

	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值