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,而且1213=106993205379072 这个数是可以用long long存的下的。

那么我们就将每一个序列看成应该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
原创粉丝点击