一道hash题

来源:互联网 发布:网络嗅探器 安卓 编辑:程序博客网 时间:2024/05/21 21:36

Description

 春天到了,百花齐放,西湖公园里新设置了许多花坛,设计师想用不同的花摆出不同的图案以吸引游人,于是设计了各种图案并且在花圃中选好了要摆放的花。不幸的是负责搬运和摆放的工人因为临时有事,只将花放到花架上就匆匆离开了,并没有按照设计师原来的设计方案摆放,结果花坛杂乱不堪,设计师只好自己来调整花的位置。由于设计师通常从事脑力劳动,较少从事搬运和摆放花盆的体力工作,所以请你帮忙找出一种移动方法使工作量最小。

  不同种类的花有不同的类型编号,虽然地球上花的种类很多,但因为公园里的花不超过1,000,000种,所以花的类型编号不超过1,000,000。另一方面,出于美学考虑,一个花坛里摆放的不同种类的花不超过3种,且不同种类的花的数量不可太接近,对于任意两种花,数量多的花的盆数至少是数量少的花的2倍。

  花坛是正六边形的,共摆放有19盆花,每盆花都放在一个转盘上,转动一盆花下面的转盘,会使周围的6盆花顺时针或逆时针移动一个位置(但不可把花转到花坛外),称为一次操作。你的任务:用最少的操作使花坛由初始状态转化为符合设计图纸的目标状态。 例如:
这里写图片描述

初始状态              目标状态

  如图,只需将处于圆心位置的那盆花的转盘顺时针转动一个位置,红色的花就移动到了目标位置。

Input Format

 输入文件共11行,1-5行描述花坛的初始状态,7-11行表示花盆应摆放的位置。中间以空行分隔。5行数字分别表示花坛的5个行,其中第1、5两行有3个整数,第2、4两行有4个整数,第3行有5个整数,表示每一行的花的类型,不同的数代表不同种类的花。

Output Format

输出文件第一行包含一个整数T即最少的操作数,数据保证20步之内有解。以下T行输出操作序列,每行代表一次操作,包括3个整数 , , ,( , )表示第i步转动第 行,第 盆花下的转盘,当 为0时表示向顺时针方向转动, 为1时表示向逆时针方向转动,如有多种方案,任意输出其中一种即可。

Sample Input
1 1 1
1 2 1 1
1 1 1 1 1
1 1 1 1
1 1 1

1 1 1
1 1 1 1
1 1 2 1 1
1 1 1 1
1 1 1

Sample Output
1
3 2 0

思路:很明显这是一道广搜题,但如果是普通的搜,就会超时。
我们可以发现,在广搜的时候,会搜到很多重复的状态,因此多了很多的时间复杂度,那么我们可以将这些状态存下来,然后在搜索的时候判断是否搜过,便能减少很多复杂度。
这里介绍一种处理方法:hash。
就是根据数字的特征去存储数据,这样查找起来方便,特别对于大数字但是数据量少的时候,就格外好用(类似于离散化)
但是坑爹的是,这道题普通的hash还过不了。必须要加上链表优化。
我们在普通hash的时候,若这一位有用过,那么就单纯的+1就好了。
这样显然会很慢。那么我们就通过一种链表的方法:把同余的点连起来,那么我们在查找这个点是否被存过的时候,就非常快。
ps:这题的状态用3进制表示起来更加省空间,不然会爆空间的样子233

    #include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<algorithm>#include<stack>#define N 1300000#define MOD 806871typedef long long LL;struct aa{    int x,id;}c[21];int yz[21],mz[21],b[9],next[N],tou[N],head,tail,bs[N];LL q[N],cs,mb;bool cmp(aa x,aa y){return x.x<y.x;}void ha(LL x){    int j=x%MOD;    if (!tou[j]){        tou[j]=tail+1;        q[++tail]=x;        bs[tail]=bs[head]+1;        return;    }     int last;    j=tou[j];    while (j){        if (q[j]==x)return;        last=j;        j=next[j];    }    next[last]=tail+1;    q[++tail]=x;    bs[tail]=bs[head]+1;    return;}LL rturn(int x,int zt){    LL sta=q[zt];    int bz[29];    for (int i=19;i>=1;i--)bz[i]=sta%3,sta/=3;    if (x==5||x==6){        int p=bz[x-4];        bz[x-4]=bz[x-1];bz[x-1]=bz[x+4];bz[x+4]=bz[x+5];bz[x+5]=bz[x+1];bz[x+1]=bz[x-3];bz[x-3]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    if (x==9||x==10||x==11){        int p=bz[x-5];        bz[x-5]=bz[x-1];bz[x-1]=bz[x+4];bz[x+4]=bz[x+5];bz[x+5]=bz[x+1];bz[x+1]=bz[x-4];bz[x-4]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    if (x==14||x==15){        int p=bz[x-5];        bz[x-5]=bz[x-1];bz[x-1]=bz[x+3];bz[x+3]=bz[x+4];bz[x+4]=bz[x+1];bz[x+1]=bz[x-4];bz[x-4]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    return 0;}LL lturn(int x,int zt){    LL sta=q[zt];    int bz[29];    for (int i=19;i>=1;i--)bz[i]=sta%3,sta/=3;    if (x==5||x==6){        int p=bz[x-1];        bz[x-1]=bz[x-4];bz[x-4]=bz[x-3];bz[x-3]=bz[x+1];bz[x+1]=bz[x+5];bz[x+5]=bz[x+4];bz[x+4]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    if (x==9||x==10||x==11){        int p=bz[x-1];        bz[x-1]=bz[x-5];bz[x-5]=bz[x-4];bz[x-4]=bz[x+1];bz[x+1]=bz[x+5];bz[x+5]=bz[x+4];bz[x+4]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    if (x==14||x==15){        int p=bz[x-1];        bz[x-1]=bz[x-5];bz[x-5]=bz[x-4];bz[x-4]=bz[x+1];bz[x+1]=bz[x+4];bz[x+4]=bz[x+3];bz[x+3]=p;        LL xx=0;        for (int i=1;i<=19;i++) xx=xx*3+bz[i];        return xx;    }    return 0;}void bfs(LL x){    head=0;tail=0;    ha(x);    while (head<=tail){        head++;        for (int i=1;i<=7;i++){            LL ls=lturn(b[i],head);            ha(ls);            if (ls==mb){                printf("%d\n",bs[tail]);                exit(0);            }            LL rs=rturn(b[i],head);            ha(rs);            if (rs==mb){                printf("%d\n",bs[tail]);                exit(0);            }        }    }}int main(){    #ifndef ONLINE_JUDGE    freopen("flowers.in","r",stdin);    freopen("flowers.out","w",stdout);    #endif    for (int i=1;i<=19;i++)scanf("%d",&c[i].x),c[i].id=i;    std::sort(c+1,c+20,cmp);    bs[0]=-1;    int j=-1;    c[0].x=-1;;    for (int i=1;i<=19;i++)      if (c[i].x!=c[i-1].x)yz[c[i].id]=++j;else yz[c[i].id]=j;    for (int i=1;i<=19;i++)scanf("%d",&c[i].x),c[i].id=i;    std::sort(c+1,c+20,cmp);    b[1]=5;b[2]=6;b[3]=9;b[4]=10;b[5]=11;b[6]=14;b[7]=15;    j=-1;    for (int i=1;i<=19;i++)    if (c[i].x!=c[i-1].x)mz[c[i].id]=++j;else mz[c[i].id]=j;    for (int i=1;i<=19;i++)cs=cs*3+yz[i];    for (int i=1;i<=19;i++)mb=mb*3+mz[i];    if (cs==mb){        printf("0");        return 0;    }    bfs(cs);    return 0;} 
0 0
原创粉丝点击