您的位置:首页 > 其它

HDU 3567 Eight II (搜索)

2016-08-26 13:38 357 查看
题意:给出两个状态的八数码,问输出第一个状态转移到第二个状态的满足以下条件的方案

1.步骤最少

2.字典序最小

如果直接进行转移,有几个很明显的问题,一时间不足,二如果双向BFS字典序不好处理,但是由于这道题的特殊性,我们只需要从一个状态转移到另一个状态,假设第一个输入为初状态,可以归纳为九类:012345678,102345678,120345678,123045678,123405678,123450678,123456078,123456708,123456780,分别作为初状态,第二个输入无非就是根据这些状态进行映射转移,由康托展开可以知道最多为3600000个状态,直接预处理出这九个状态的方案解决问题

#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 3600000

char d[]={"dlru"};
int dir[][5]={{1,0},{0,-1},{0,1},{-1,0}};

struct node
{
int step;
int index;
int cant;
char g[11];
}t[maxn];

int fa[10][maxn];
int ans[10][maxn];
int vis[10][maxn];

int fac[]= {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800}; ///0~8
int cantor(char ss[])
{
int s[10];
for(int i=0; i<9; i++)
s[i]=ss[i]-'0';
int sum=0;
for(int i=0; i<9; i++)
{
int num=0;
for(int j=i+1; j<9; j++)
if(s[j]<s[i]) num++;
sum+=(num*fac[9-i-1]);
}
return sum+1;
}

bool judge(int x,int y)
{
return x>=0&&x<3&&y>=0&&y<3;
}

int que[maxn];
void bfs(int k,char s[])
{
int l=0,r=-1;
int cant=cantor(s);
que[++r]=cant;
memcpy(t[cant].g,s,sizeof t[cant].g);
t[cant].index=k;
fa[k][cant]=-1;
t[cant].cant=cant;
vis[k][cant]=1;
t[cant].step=1;
while(l<=r)
{
int f=que[l++];
int x=t[f].index/3;
int y=t[f].index-3*x;
for(int i=0;i<4;i++)
{
int _x=x+dir[i][0];
int _y=y+dir[i][1];
if(judge(_x,_y))
{
node temp=t[f];
swap(temp.g[temp.index],temp.g[_x*3+_y]);
temp.cant=cantor(temp.g);
if(vis[k][temp.cant]) continue;
vis[k][temp.cant]=temp.step+1;
ans[k][temp.cant]=i;
fa[k][temp.cant]=f;
temp.index=_x*3+_y;
temp.step++;
t[temp.cant]=temp;
que[++r]=temp.cant;
}
}
}
}

void print(int k,int st,int ed)
{
if(ed==st) return ;
print(k,st,fa[k][ed]);
printf("%c",d[ans[k][ed]]);
}

int main()
{
char str[20];
strcpy(str,"012345678");
bfs(0,str);
strcpy(str,"102345678");
bfs(1,str);
strcpy(str,"120345678");
bfs(2,str);
strcpy(str,"123045678");
bfs(3,str);
strcpy(str,"123405678");
bfs(4,str);
strcpy(str,"123450678");
bfs(5,str);
strcpy(str,"123456078");
bfs(6,str);
strcpy(str,"123456708");
bfs(7,str);
strcpy(str,"123456780");
bfs(8,str);
int T;
int ca=1;
scanf("%d",&T);
while(T--)
{
char str1[20],str2[20];
int num[20];
memset(num,0,sizeof num);
int px,cant1,py,cant2;
scanf("%s%s",str1,str2);
for(int i=0,j=1; i<9; i++)
{
if(str1[i]=='X') str1[i]='0',px=i;
if(str1[i]!='0') num[str1[i]-'0']=j,str1[i]=j+'0',j++;
}
for(int i=0;i<9;i++)
{
if(str2[i]=='X') str2[i]='0';
str2[i]=num[ str2[i]-'0' ]+'0';
}
cant1=cantor(str1);
cant2=cantor(str2);
printf("Case %d: %d\n",ca++,vis[px][cant2]-1);
print(px,cant1,cant2);
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: