JZOJ1444. 交换【推荐】
来源:互联网 发布:htc手机数据连接不上 编辑:程序博客网 时间:2024/06/16 04:02
题目
Description
给定1到N的一个排列,再给定一些允许的交换方法,要求用最少的交换次数把该排列变为1,2,3,,,N。
Input
第一行包含两个整数N(1<=N<=12)和M(1<=M<=N*(N-1)/2),表示序列的长度以及允许的交换方案。
第二行输入1到N个初始排列情况。
接下来M行,每行两个整数A和B描述一个允许的交换方案,表示允许把当前排列中的第A个数和第B个数进行交换,保证A和B不相同。
输入保证一定存在解。
Output
输出一个整数表示最少需要的交换次数。
Sample Input
输入1:
2 1
2 1
1 2
输入2:
3 2
2 1 3
1 3
2 3
输入3:
5 5
1 2 3 4 5
1 5
2 5
1 4
1 1
3 5
Sample Output
输出1:
1
输出2:
3
输出3:
0
分析
观察数据范围,发现这里的N很小,也许可以用暴力来处理。
但是,如果用暴力的话,会出现很多重复状态,而且效率不高。
开始的起始状态我们是知道的,最终转移到的状态我们也是知道的,而且每种操作的改变对于正着做和反着做都是相同的。
- 所以这题应该用双向广搜
不过,我们如何记录它的状态?
开应该12维的布尔数组是不太科学的,
因为N很小只用12,而且
那么我们就将每一个序列看成应该12进制的数,再将它转换成为应该10进制数。
这样,我们就可以将每一个序列变成一个数。
然而,这里可能出现的状态不是很多,我们可以用hash表来储存和判重。
Code(c++)
#include <cstdio>#include <algorithm>#include <cstring>#include <string.h>#include <cmath>#include <stdlib.h>#include <math.h>#define ll long long#define mo 1000007using namespace std;ll ha[mo];bool bz[mo];int g[mo];ll data[3*mo],da1[3*mo],z[15],s;int a[15],t[15],f[15],cz[150][2];int n,m,l,now;int hash(ll x){ int k=x%mo; while((ha[k])&&(ha[k]!=x))k=(k+1)%mo; return k;}ll zz(){ ll sum=0; for(int i=1;i<=n;i++) sum+=t[i]*z[n-i]; return sum;}void aa(ll x){ for(int i=1;i<=n;i++) { f[i]=x/z[n-i]; x=x%z[n-i]; }}int main(){ z[0]=1; for(int i=1;i<=13;i++) z[i]=z[i-1]*12; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); t[i]=i-1; a[i]--; } for(int i=1;i<=m;i++) scanf("%d%d",&cz[i][0],&cz[i][1]); da1[1]=zz(); l=hash(da1[1]); ha[l]=da1[1]; bz[l]=1; memcpy(t,a,sizeof(t)); data[1]=zz(); l=hash(data[1]); ha[l]=data[1]; if(da1[1]==data[1]) { printf("0\n"); return 0; } int i=0,j=1,p=0,q=1; while((i<j)&&(p<q)) { i++; aa(data[i]); now=g[hash(data[i])]; for(int k=1;k<=m;k++) { memcpy(t,f,sizeof(t)); l=t[cz[k][0]]; t[cz[k][0]]=t[cz[k][1]]; t[cz[k][1]]=l; s=zz(); l=hash(s); if(ha[l]==s) { if(bz[l]) { printf("%d\n",g[l]+now+1); return 0; } } else { j++; data[j]=s; ha[l]=s; bz[l]=0; g[l]=now+1; } } p++; aa(da1[p]); now=g[hash(da1[p])]; for(int k=1;k<=m;k++) { memcpy(t,f,sizeof(t)); l=t[cz[k][0]]; t[cz[k][0]]=t[cz[k][1]]; t[cz[k][1]]=l; s=zz(); l=hash(s); if(ha[l]==s) { if(!bz[l]) { printf("%d\n",g[l]+now+1); return 0; } } else { q++; da1[q]=s; ha[l]=s; bz[l]=1; g[l]=now+1; } } }}
2 0
- JZOJ1444. 交换【推荐】
- JZOJ1444. 交换【推荐】(2017.8B组)
- JZOJsenior1444. 交换【推荐】
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 推荐一个不错的高权重链接交换平台,一秒钟即可被收录
- 新书推荐:百问FreeSwitch:VOIP 软交换 实用案例解答 余洪涌著
- 推荐
- 推荐
- 推荐~
- 推荐
- 推荐
- java中特殊的流程控制语句(break,continue,return)
- 开发者MAC电脑里的十八般兵器
- Android通知栏
- CodeForces 609C Load Balancing
- SDUT 2133 数据结构实验之栈三:后缀式求值
- JZOJ1444. 交换【推荐】
- python学习——TCP编程
- 杭电ACM--HDU-1021斐波拉契
- CocosCreator
- Spark学习(3)--Scala语言学习
- Leetcode 319 : Bulb Switcher
- 计蒜客 挑战难题 跳跃游戏
- BestCoder 2nd Anniversary
- Spark日志分析案例