hdoj1043,eight
2015-09-08 08:10
363 查看
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
;
int position;
string step;
};
//记录路径的数列
string inversionPath[MAXN];
//康托序列
int fac
={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;
}
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
;
int position;
string step;
};
//记录路径的数列
string inversionPath[MAXN];
//康托序列
int fac
={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;
}
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- 2015 Multi-University Training Contest 6 Solutions
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- ACM题库以及培养策略