hdu3567 Eight II 康拓展开+打表+路径回溯+映射
来源:互联网 发布:万方数据库免费入口 编辑:程序博客网 时间:2024/05/17 02:59
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567
题意:给你一个八数码的起始和终止状态,让你打印路径,要求字典序最小,长度最短,保证输入数据必有解。
思路:2000ms 200组数据,平均10ms一组数据。用A*的话,可能会tle,而且还不能保证字典序最小。所以直接打表,考虑到起点,终点不定,所以需要映射,比如我把起点564178X23映射成123456X87(即12345678X,将7和X交换位置),然后按照这个映射方法,把终点7568X4123映射成5126X3487,那么起点564178X23到终点7568X4123的路径肯定等于123456X87到5126X3487的路径。所以我们可以提前打表,然后通过映射,直接输出表就好了。 但是考虑到X的位置有九种,每次的位置不定,所以我们需要打九次表,然后根据起始状态的X的位置,选择不同的表,输出。
可以先写这道题:http://acm.hdu.edu.cn/showproblem.php?pid=1043
题解:http://blog.csdn.net/acmlzq/article/details/54427716
代码:
#include<cstdio>#include<cstring>#include<string>#include<queue>#include<cmath>#include<vector>#include<map>#include<stack>#include<iostream>#include<algorithm>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define scanfprint() freopen("input.txt","r",stdin)#define printfprint() freopen("output.txt","w",stdout)#define mem(a,b) memset(a,b,sizeof(a))const int spot=1000+10;const int edge=100000+10;const int maxn=362880+10;const double pi=acos(-1.0);const int mod=1e9+7;const double ips=0.000001;const int c_n=9;bool c_flag[c_n+10];int c_a[c_n+10],fact[15]= {0,1,1,2,6,24,120,720,5040,40320,362880},m[11][maxn],num=0,casen=0;struct stu1{ int pre; //上一个 char dir; //方向} memory[11][maxn]; //打表 //第一个下标表示第几个表(几对应的是X所在的位置)struct stu2{ int c_v,num,coor; //康拓值,打表的下标,表里的下标} s,t;bool flag[maxn]; //int cantor() //康拓展开 c_a[1]到c_a[n]表示一个全排列,返回的ans表示康拓值(从0开始){ mem(c_flag,0); int i,j,sum=0,ans=0,k; for(i=1,k=c_n; i<=c_n; i++,k--) { sum=0; for(j=c_a[i]-1; j>=1; j--) { if(!c_flag[j]) sum++; } c_flag[c_a[i]]=1,ans+=sum*fact[k]; } return ans;}void inverse_cantor(int c_m) //康拓逆展开 传入的m是康拓值(从0开始),最终的c_a[1]到c_a[n]是m对应的排列{ mem(c_flag,0); int i,j,k,sum; for(i=1,k=c_n; i<=c_n; i++,k--) { sum=c_m/fact[k]+1; for(j=1; j<=c_n; j++) { if(!c_flag[j]) sum--; if(!sum) break; } c_a[i]=j,c_flag[j]=1,c_m%=fact[k]; }}void bfs(int in){ int i,temp; s.c_v=cantor(),s.num=0,s.coor=in; flag[s.c_v]=1; m[in][s.c_v]=0; queue<stu2>q; q.push(s); while(!q.empty()) {dd s=q.front(); q.pop(); inverse_cantor(s.c_v); for(i=0; i<4; i++) { if(!i) //下 { if(s.coor<7) { swap(c_a[s.coor],c_a[s.coor+3]); t.c_v=cantor(); if(!flag[t.c_v]) { t.coor=s.coor+3,t.num=++num; memory[in][num].dir='d',memory[in][num].pre=s.num; m[in][t.c_v]=num; flag[t.c_v]=1; q.push(t); } swap(c_a[s.coor],c_a[s.coor+3]); } } if(i==1) //左 { if(s.coor!=1&&s.coor!=4&&s.coor!=7) { swap(c_a[s.coor],c_a[s.coor-1]); t.c_v=cantor(); if(!flag[t.c_v]) { t.coor=s.coor-1,t.num=++num; memory[in][num].dir='l',memory[in][num].pre=s.num; m[in][t.c_v]=num; flag[t.c_v]=1; q.push(t); } swap(c_a[s.coor],c_a[s.coor-1]); } } if(i==2) //右 { if(s.coor!=3&&s.coor!=6&&s.coor!=9) { swap(c_a[s.coor],c_a[s.coor+1]); t.c_v=cantor(); if(!flag[t.c_v]) { t.coor=s.coor+1,t.num=++num; memory[in][num].dir='r',memory[in][num].pre=s.num; m[in][t.c_v]=num; flag[t.c_v]=1; q.push(t); } swap(c_a[s.coor],c_a[s.coor+1]); } } if(i==3)//上 { if(s.coor>3) { swap(c_a[s.coor],c_a[s.coor-3]); t.c_v=cantor(); if(!flag[t.c_v]) { t.coor=s.coor-3,t.num=++num; memory[in][num].dir='u',memory[in][num].pre=s.num; m[in][t.c_v]=num; flag[t.c_v]=1; q.push(t); } swap(c_a[s.coor],c_a[s.coor-3]); } } } }}void print(int in,int n,int step){ if(!n) { printf("Case %d: %d\n",++casen,step); return ; } print(in,memory[in][n].pre,step+1); printf("%c",memory[in][n].dir);}void init() //打九张表{ int i,j,temp; for(i=1; i<=9; i++) { mem(flag,0),num=0; for(j=1; j<=9; j++) c_a[j]=j; swap(c_a[i],c_a[9]); bfs(i); }}void solve() //先映射{ int a1[15],a2[15],temp1[15],temp2[15],i,j,sub; char s1[15],s2[15]; scanf("%s%s",s1+1,s2+1); for(i=1; i<=9; i++) { if(s1[i]=='X') sub=i,a1[i]=9; else a1[i]=s1[i]-'0'; temp1[i]=i; a2[i]=s2[i]=='X'?9:s2[i]-'0'; } swap(temp1[sub],temp1[9]); for(i=1; i<=9; i++) temp2[a1[i]]=temp1[i]; for(i=1; i<=9; i++) c_a[i]=temp2[a2[i]]; int ans=cantor(); print(sub,m[sub][ans],0); puts("");}int main(){ init(); int nn; scanf("%d",&nn); while(nn--) { solve(); }}
0 0
- hdu3567 Eight II 康拓展开+打表+路径回溯+映射
- HDU3567:Eight II(康拓展开+预处理)
- HDU3567:Eight II(康拓展开+预处理) (B)
- HDU1043:Eight HDU3567:Eight II(康拓展开+bfs搜索)
- hdu3567 Eight II(IDA*+康托展开)
- hdu1043 Eight 康拓展开+bfs打表
- HDU356 Eight II(康拓展开+预处理)
- HDU3567 Eight II —— IDA*算法
- HDOJ 题目1043 Eight(单向BFS,康拓展开,打表)
- hdu3567 Eight II (双向广搜+哈希)
- HDU 1043 Eight(BFS+康拓展开)
- HDU Eight( 康拓展开)
- POJ 1077 Eight A*算法 IDA*算法 康拓展开
- POJ 1077 Eight BFS + 康拓展开式
- POJ 1077 Eight(康拓展开 BFS 双向BFS)
- HDU 1043 Eight(A* + 奇偶剪枝 + 康拓展开)
- hdu1430(康拓展开+bfs打表)
- hdu 1430 bfs + 打表 + 康拓展开
- Twitter的分布式自增ID算法snowflake - C#版
- 10 Java并发编程2-Thread类总结
- android四种基本布局之FrameLayoutAndTableLayout
- 性能测试的测试用例
- uva 193 Graph Coloring
- hdu3567 Eight II 康拓展开+打表+路径回溯+映射
- php时间戳的转换
- ubuntu16.04+qt 一些问题
- shell脚本实现删除过期数据库中的数据
- 400. Nth Digit
- DTW(动态时间规整算法)
- Seating On Bus
- ROS入门_1.14 编写及测试简单的消息发布器和订阅器 (C++)
- java之线程池的使用