第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢。
然后想到用map函数,就8!个不同的排列,换成字符串用map标记。然后又交一发果断超时,伤心,最恨超时,还不如来个wa算了。
然后卡着了,后来上网上搜,要用康托展开,康托展开是什么鬼?然后学习了一下,就是个映射,感觉和map差不多。
http://blog.csdn.net/zhongkeli/article/details/6966805这个学习一下康托展开。
其实本题的关键不是康托展开,而是置换。
以12345678为起始状态开始搜它经过3种变换能到达的所有状态的最小步数,每搜到一个记录下来,可以用康托展开,也可以用C++ STL库里的map
所以只要搜一次就够了,然后记录。那么咋转置呢。举个列子 初态为65871234 目标态为87125463,那么初态和12345678比较,6和1对应,5和2对应
8和3对应......,所以目标态的8为初态的第三位,而初态的第三位对应12345678中的三,所以目标态第一位转为3,同理第2位转为4......
最后的到状态为34562817,所以只要知道12345678转为34562817的最小步数就为所求。
下面给两段代码一个是用map写的一个是用康托展开写的。map写的运行时间比较慢200多Ms,不过时间足够,题目好像是给了5s吧,
康托展开是46ms.
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1430;
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<stdlib.h> 6 #include<math.h> 7 #include<queue> 8 #include<stack> 9 #include<cstdio> 10 #include<map> 11 void bfs(); 12 using namespace std; 13 void AA(char *p,char *q); 14 void BB(char *p,char *q); 15 void CC(char *p,char *q); 16 int N=50005; 17 map<string,int>my; 18 char t[10]="12345678"; 19 char a[41000][100];//总共有8!的状态每个状态对应一个数然后用数组存变换的步奏 20 typedef struct pp 21 { 22 23 char ab[10]; 24 int n; 25 26 } ss;//开结构体存步数。 27 int main(void) 28 { 29 30 int n,i,j,k,p,q; 31 char aa[10]; 32 char bb[10]; 33 char cc[10]; 34 bfs(); 35 while(scanf("%s %s",aa,bb)!=EOF) 36 { 37 int yu=0; 38 for(i=0; i<8; i++) 39 { 40 for(j=0; j<8; j++) 41 { 42 if(bb[i]==aa[j]) 43 { 44 cc[yu++]=j+1+'0'; 45 } 46 } 47 } 48 cc[8]='