您的位置:首页 > 其它

hdu 1067 Gap

2017-07-16 21:32 423 查看
这道题和hdu1043 Eight问题可以认为是同一类问题,

针对这道题,是手动实现的hash, 而Eight问题是利用康托展开式 ,康托数和排列一一对应本质还是hash

这两道是典型的状态搜索题,

这里纪念下

下面是ac代码,思路源于其他网友,这里借鉴

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;

struct Node{

int g[4][8];

int step;

bool operator ==(const Node& other)const{

for(int i=0;i<4;i++){
for(int j=0;j<8;j++)
if(g[i][j]!=other.g[i][j])return false;
}
return true;
}

long long Hash(){

long long code=0;

for(int i=0;i<4;i++){
for(int j=0;j<8;j++){

code+=(long long)(code<<(long long)1)+ (long long) (g[i][j]);

}
}
return code;
}

};

const int maxn=100007;

long long Hash[maxn];

Node Start,End;
queue<Node> q;

void  Insert(long long value){

int v=value%maxn;

while(Hash[v]!=-1&&Hash[v]!=value){

v+=31;  // hash again
v%=maxn;
}

if(Hash[v]==-1){
Hash[v]=value;
}
}

bool isInsert(long long value){

int v=value%maxn;

while(Hash[v]!=-1&&Hash[v]!=value){

v+=31;
v%=maxn;
}

if(Hash[v]==-1) return false;

return true;
}

void initStart(){

for(int i=0;i<4;i++){

Start.g[i][0]=0;
for(int j=1;j<8;j++){

scanf("%d",&Start.g[i][j]);
}

}
}

void initEnd(){

for(int i=0;i<4;i++){

for(int j=0;j<7;j++){
End.g[i][j]=(i+1)*10+j+1;
}
End.g[i][7]=0;
}

}

void bfs(){

Node first,next;
q.push(Start);

while(!q.empty()){

first=q.front();
q.pop();

for(int i=0;i<4;i++){

for(int j=0;j<8;j++){

//find the blank
if(!first.g[i][j]){

next=first;

next.step++;
//find the val

int val=first.g[i][j-1]+1;
int fx,fy;
bool flag=false;
// base the rule no node can move 7 or blank right
if(val==1||val%10==8) continue;

for(int p=0;p<4;p++){
for(int k=0;k<8;k++){

if(first.g[p][k]==val){
fx =p,fy=k;
flag=true;
}
}
}

// find the value that can move the blank
if(flag){

int tmp=next.g[i][j];
next.g[i][j]=first.g[fx][fy];
next.g[fx][fy]=tmp;

if(next==End){

printf("%d\n",next.step);
return ;
}
long long value=next.Hash();

if(!isInsert(value)){

Insert(value);

q.push(next);
}
}

}
}
}
}

printf("-1\n");
}

void soluation(){

// first move 11,21,31,41 to the first place;

int i,j;
int r=0;
int tmp=4;

//search 11,21,31,41
while(tmp--)
for( i=0;i<4;i++){
for(j=1;j<8;j++){

if(Start.g[i][j]==(r+1)*10+1){
Start.g[r++][0]=Start.g[i][j];
Start.g[i][j]=0;
}
}

}

if(Start==End){

printf("0\n");

return ;
}
bfs();

}

int main()
{
int n;
cin>>n;
int t=n;

initEnd();
while(t--){

memset(Hash,-1,sizeof(Hash));

initStart();
while(!q.empty()) q.pop();
soluation();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: