20191024
ac之前,超时了n发,怎么改怎么超,程序员日 ac的第一道题。
超时原因:
(1)map判重
(2)同时使用了康托展开和反康托展开,用一个一位数组代替后者,即可;
知识点:
(1)康托展开
(2)string记录路径
解题框架:
1,读入数据,有太多空格,建议采用scanf一个个读入,scanf遇到空格和回车会停止的;
记录初始状态下的x的位置;
2,计算出初始状态的hash值,表示出初始状态的数据排列;计算出终点的hash值;
3,bfs:
(1)将一位坐标转化为二维坐标,计算出子状态的排列顺序,计算出子状态的hash值;
(2)判断子状态的hash值是否出先过,以及是否是终点;
(3)用string记录路径
#include<map>
#include<vector>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int num=362880+10;
struct node
{
string path;//¼Ç¼·¾¶
int e[11];
int hash;//¹þÏ£Öµ
int x;//0µÄλÖÃ
}st;
bool vis[num];
int en=0;//1234567890µÄ¹þÏ£Öµ?
int f[12]={1,1,2,6,24,120,720,5040,40320,362880};
int cantor(int *a,int n)
{
int ans=0,x;
for(int i=0;i<n;i++)
{
x=0;
for(int j=i+1;j<n;j++)
{
if(a[i]>a[j]) x++;
}
ans+=x*f[n-i-1];
}
return ans;
}
void recantor(int *a,int x,int n)
{
vector<int>v; //´æ·Åµ±Ç°µÄÊý
for(int i=0;i<9;i++)
v.push_back(i);
int r,t;
for(int i=0;i<n;i++)
{
r=x%f[n-i-1];
t=x/f[n-i-1];
x=r;
sort(v.begin(),v.end());
a[i]=v[t];
v.erase(v.begin()+t);
}
return ;
}
void bfs(void)
{
int nx[4]={-1,0,1,0},tx;
int ny[4]={0,1,0,-1},ty;
node u,v;
string dir="urdl";
queue<node>q;
vis[st.hash]=true;
q.push(st);
while(!q.empty())
{
u=q.front();q.pop();
for(int i=0;i<4;i++)
{
tx=u.x/3+nx[i];ty=u.x%3+ny[i];
if(tx<0||ty<0||tx>2||ty>2) continue;
v.x=tx*3+ty;
for(int i=0;i<9;i++) v.e[i]=u.e[i];
swap(v.e[u.x],v.e[v.x]);
v.hash=cantor(v.e,9);
if(vis[v.hash]==0)
{
v.path=u.path+dir[i];
if(v.hash==en)
{
int L=v.path.size();
for(int i=0;i<L;i++)
printf("%c",v.path[i]);
return ;
}
q.push(v);
vis[v.hash]=true;
}
}
}
printf("unsolvable\n");
return ;
}
void read_(void)
{
char str[30];
int a[10],cnt=0;
for(int i=0;i<9;i++)
{
scanf("%s",str);
if(str[0]=='x') {
st.x=cnt;//¼Ç¼0ÔÚÄĸöλÖã»
str[0]='0';
}
if(str[0]>='0'&&str[0]<='9')
st.e[cnt++]=str[0]-'0';
}
st.hash=cantor(a,9);
for(int i=0;i<9;i++)
a[i]=i+1;
a[8]=0;
en=cantor(a,9);
return ;
}
int main()
{
read_();
bfs();
return 0;
}