Sicily 1866.Gene Reprogram 一种经典的hash方法
http://202.116.77.69/sicily/show_problem.php?pid=1866
【题意】序列a 变成序列b 的最少步数 可执行的操作有
1. 把交换字符串的前两个字符
2. 把最前面的那个字符换到最后
【思路】 广搜 但是有几个地方要注意的
1. 每一位有4种可能 最多有12位 所以最多的状态数是4^12 但是ATGC 每一种的个数并不会改变而且 求的是组合而不是排列 所以状态空间的上限没有这么多 而是num= N!/A!*C!*T!*G!
2. 可以用0 1 2 3 分别表示ACTG 即一个四进制位表示 一个状态就是一个四进制数值 因为最多是12位 所以这个数值最大就是4^12 判重的数组开 n
可以给每一个排列分配一个哈希值 这里的方法是
按字典序的大小给所有排列顶一个全序 给这个排列的哈希值就是它在这个全序里的序号
枚举当前排列的每一位 累加上当前为小于它而前面所有为都一样的排列个数
如 32120
枚举第一位时是
0****
1****
2****
枚举第二位时是
30***
31***
第三位
320**
。。。。
而计算某个带有重复元素的全排列的个数 的方法为 n!/ (n1!* n2!* n3!....)
n是序列的长度 ni 是第i中元素的总个数
total是原串求得的 n!/ (n1!* n2!* n3!....)
int gethash(int a[]) { int sum=total; int ans=0; for(int i=0;i<n;i++) { for(int j=0;j<a[i];j++) if(c[j]) ans+=sum*c[j]/(n-i)); //即sum/ ((n-i)/c[j]) 在草稿上演示一遍就知道了 sum=sum*c[a[i]]/(n-i); c[a[i]]--; } }
灰常好的哈希方法~ 代码也很简练