您的位置:首页 > 其它

一道hash题

2015-09-27 22:06 459 查看
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 806871
typedef long long LL;
struct aa{
int x,id;
}c[21];
int yz[21],mz[21],b[9],next
,tou
,head,tail,bs
;
LL q
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hash NOIP 广搜