JZOJsenior1444. 交换【推荐】
来源:互联网 发布:王者荣耀kda最新算法 编辑:程序博客网 时间:2024/06/05 08:08
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
Data Constraint
说在前面:
最近时间紧张,没时间打博客了……咳咳……
思路:
n比较小(其实再大一点这题就做不出来了),考虑搜索
dfs不可能选择,而bfs可以试试
好,那么现在我们就考虑如何bfs切掉这道题
注意一点,起始状态和终止状态都已经给出了,为了提高效率,我们用双向bfs
(由于搜索树从一棵变成两棵,双向复杂度是单向的开方级别,有兴趣看证明的可以百度)
还有一个问题,除非像最基础的倒水问题,否则bfs会出现大量没有用的状态
但是我们不可能用12维布尔数组存下出现过的状态,有一个简单的解决办法:散列表(hash)
把当前状态压成一个十进制下的十三进制数,不超过long long,所以我们把哈希也开long long即可
比赛的时候想到了双向bfs,但没想到压位+hash,只用了字符串+hash存状态,才TLE50
接下来就很easy了
从起始状态和终止状态开始扩展,只要有一个状态出现两次,直接输出退出
(由于和谐的空间限制,我的哈希开的不大,虽说是正解但T了一个点,看情况适当打表)
代码(常数大,又臭又长):
const maxn=1000007;type arr=array[0..12]of longint;var que1,que2,hash1,hash2:array[0..maxn]of record s:int64; sum:longint; end; x,y:array[0..100]of longint; n,m,i,j,h1,t1,h2,t2:longint; flag:boolean; temp:int64; a,b:arr;procedure swap(var x,y:longint);var z:longint;begin z:=x; x:=y; y:=z;end;function turn(t:arr):int64;var tp:int64; i:longint;begin turn:=0; tp:=1; for i:=12 downto 1 do begin if t[i]>0 then turn:=turn+t[i]*tp; tp:=tp*13; end;end;procedure return(n:int64;var t:arr);var i:longint;begin fillchar(t,sizeof(t),0); for i:=12 downto 1 do begin t[i]:=n mod 13; n:=n div 13; end;end;function find1(x:int64):boolean;var now:longint;begin now:=x mod maxn; if hash1[now].s=0 then exit(true); if hash1[now].s=x then exit(false); now:=(now+1)mod maxn; while (hash1[now].s<>0)and(hash1[now].s<>x)do begin inc(now); if now=maxn then now:=0; end; if hash1[now].s=0 then exit(true); if hash1[now].s=x then exit(false);end;procedure into1(x:int64;y:longint);var now:longint;begin now:=x mod maxn; if hash1[now].s=0 then begin hash1[now].s:=x; hash1[now].sum:=y; exit; end; now:=(now+1)mod maxn; while (hash1[now].s<>0)and(hash1[now].s<>x) do begin inc(now); if now=maxn then now:=0; end; hash1[now].s:=x; hash1[now].sum:=y;end;function find2(x:int64):boolean;var now:longint;begin now:=x mod maxn; if hash2[now].s=0then exit(true); if hash2[now].s=x then exit(false); now:=(now+1)mod maxn; while (hash2[now].s<>0)and(hash2[now].s<>x)do begin inc(now); if now=maxn then now:=0; end; if hash2[now].s=0 then exit(true); if hash2[now].s=x then exit(false);end;procedure into2(x:int64;y:longint);var now:longint;begin now:=x mod maxn; if hash2[now].s=0 then begin hash2[now].s:=x; hash2[now].sum:=y; exit; end; now:=(now+1)mod maxn; while (hash2[now].s<>0)and(hash2[now].s<>x) do begin inc(now); if now=maxn then now:=0; end; hash2[now].s:=x; hash2[now].sum:=y;end;function lookfor(x:int64):longint;var now:longint;begin now:=x mod maxn; if hash1[now].s=x then exit(hash1[now].sum); while true do begin inc(now); if now=maxn then now:=0; if hash1[now].s=x then exit(hash1[now].sum); end;end;begin readln(n,m); flag:=true; for i:=1 to n do begin read(a[i]); if a[i]<>i then flag:=false; b[i]:=i; end; if flag then begin writeln(0); halt; end; for i:=1 to m do readln(x[i],y[i]); h1:=0; t1:=1; h2:=0; t2:=1; que1[1].s:=turn(a); que2[1].s:=turn(b); repeat inc(h1); if h1=maxn then h1:=0; for i:=1 to m do begin return(que1[h1].s,b); swap(b[x[i]],b[y[i]]); temp:=turn(b); if find1(temp) then begin into1(temp,que1[h1].sum+1); inc(t1); if t1=maxn then t1:=0; que1[t1].s:=temp; que1[t1].sum:=que1[h1].sum+1; end; end; inc(h2); if h2=maxn then h2:=0; if not find1(que2[h2].s)then begin writeln(que2[h2].sum+lookfor(que2[h2].s)); halt; end; for i:=1 to m do begin return(que2[h2].s,b); swap(b[x[i]],b[y[i]]); temp:=turn(b); if find2(temp)then begin into2(temp,que2[h2].sum+1); inc(t2); if t2=maxn then t2:=0; que2[t2].s:=temp; que2[t2].sum:=que2[h2].sum+1; end; end; until false;end.
- JZOJsenior1444. 交换【推荐】
- JZOJ1444. 交换【推荐】
- JZOJ1444. 交换【推荐】(2017.8B组)
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 交换
- 推荐一个不错的高权重链接交换平台,一秒钟即可被收录
- 新书推荐:百问FreeSwitch:VOIP 软交换 实用案例解答 余洪涌著
- 推荐
- 推荐
- 推荐~
- 推荐
- 推荐
- Unity 回合制战斗系统(高级篇)
- linux网络编程之断点传输文件
- Kotlin入门篇(一),基本数据类型介绍、变量和常量的声明
- Android UI
- CentOS7 matplotlib notebook 安装和使用
- JZOJsenior1444. 交换【推荐】
- 越大越聪明(输出路径问题)
- 用spark统计50年美国最常见的20个名字
- 【JAVA】数据库连接池(DBCP)的使用与操作
- codeforce-404D---Minesweeper 1D(dp)
- numpy array 增加一列(行)
- Spring 相关配置&属性注入
- Kotlin入门篇(二),如何声明函数和处理空值
- POJ