Eight POJ - 1077

HDU - 1043

八数码问题。用hash(康托展开)判重

bfs(TLE)

 #include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int fac[]={,,,,,,,,,};
bool hash_map[];
int data[][];
queue<int> q;
//data[][9]存储上一个状态,data[][10]存储到这个状态的操作,data[][11]存储这个状态中9的位置
char s[];
int mem;
int hash1(int s[])
{
int i,j,cnt,sum=;
for(i=;i<;i++)
{
cnt=;
for(j=i+;j<;j++)
if(s[j]<s[i])
cnt++;
sum+=cnt*fac[-i];
}
return sum;
}
void print(int x)
{
if(data[x][]==) return;
print(data[x][]);
if(data[x][]==)
putchar('l');
else if(data[x][]==)
putchar('r');
else if(data[x][]==)
putchar('u');
else putchar('d');
}
int main()
{
char ch;
int i,j,a,b,t,p;
while(cin.getline(s,))
{
memset(data,,sizeof(data));
memset(hash_map,,sizeof(hash_map));
b=mem=;
j=;
for(i=;s[i]!='\0';i++)
{
if(s[i]==' ') continue;
sscanf(s+i,"%c",&ch);
if(ch=='x')
{
data[b][j]=;
data[b][]=j++;
}
else
data[b][j++]=ch-'';
}
q.push(b);
t=hash1(data[b]);
hash_map[t]=true;
if(t==)
goto xxx;
while(!q.empty())
{
a=q.front();
q.pop();
p=data[a][];
if(p!=&&p!=&&p!=)
{
memcpy(data[],data[a],sizeof(data[]));
t=data[][p];
data[][p]=data[][p-];
data[][p-]=t;
data[][]=a;
data[][]=;
data[][]=p-;
t=hash1(data[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(data[b],data[],sizeof(data[b]));
q.push(b);
}
}
if(p!=&&p!=&&p!=)
{
memcpy(data[],data[a],sizeof(data[]));
t=data[][p];
data[][p]=data[][p+];
data[][p+]=t;
data[][]=a;
data[][]=;
data[][]=p+;
t=hash1(data[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(data[b],data[],sizeof(data[b]));
q.push(b);
}
}
if(p>)
{
memcpy(data[],data[a],sizeof(data[]));
t=data[][p];
data[][p]=data[][p-];
data[][p-]=t;
data[][]=a;
data[][]=;
data[][]=p-;
t=hash1(data[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(data[b],data[],sizeof(data[b]));
q.push(b);
}
}
if(p<)
{
memcpy(data[],data[a],sizeof(data[]));
t=data[][p];
data[][p]=data[][p+];
data[][p+]=t;
data[][]=a;
data[][]=;
data[][]=p+;
t=hash1(data[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(data[b],data[],sizeof(data[b]));
q.push(b);
}
}
}
printf("unsolvable");
xxx:
puts("");
while(!q.empty()) q.pop();
memset(s,,sizeof(s));
}
return ;
}

从目标状态出发,一次bfs打出所有输入对应结果的表(172ms)

 #include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int fac[]={,,,,,,,,,};
bool hash_map[];
int data[][];
int temp[];
queue<int> q;
//data[][9]存储上一个状态,data[][10]存储到这个状态的操作,data[][11]存储这个状态中9的位置
char s[];
int mem;
int hash1(int s[])
{
int i,j,cnt,sum=;
for(i=;i<;i++)
{
cnt=;
for(j=i+;j<;j++)
if(s[j]<s[i])
cnt++;
sum+=cnt*fac[-i];
}
return sum;
}
void print(int x)
{
if(x==)
putchar('r');
else if(x==)
putchar('l');
else if(x==)
putchar('d');
else putchar('u');
}
void init()
{
int i,a,b,p,t;
q.push();
for(i=;i<;i++)
data[][i]=i+;
data[][]=;
hash_map[]=;
while(!q.empty())
{
a=q.front();
q.pop();
p=data[a][];
if(p%!=)
{
memcpy(temp,data[a],sizeof(temp));
t=temp[p];
temp[p]=temp[p-];
temp[p-]=t;
temp[]=a;
temp[]=;
temp[]=p-;
t=hash1(temp);
if(!hash_map[t])
{
hash_map[t]=;
memcpy(data[t],temp,sizeof(data[t]));
q.push(t);
}
}
if(p%!=)
{
memcpy(temp,data[a],sizeof(temp));
t=temp[p];
temp[p]=temp[p+];
temp[p+]=t;
temp[]=a;
temp[]=;
temp[]=p+;
t=hash1(temp);
if(!hash_map[t])
{
hash_map[t]=;
memcpy(data[t],temp,sizeof(data[t]));
q.push(t);
}
}
if(p>)
{
memcpy(temp,data[a],sizeof(temp));
t=temp[p];
temp[p]=temp[p-];
temp[p-]=t;
temp[]=a;
temp[]=;
temp[]=p-;
t=hash1(temp);
if(!hash_map[t])
{
hash_map[t]=;
memcpy(data[t],temp,sizeof(data[t]));
q.push(t);
}
}
if(p<)
{
memcpy(temp,data[a],sizeof(temp));
t=temp[p];
temp[p]=temp[p+];
temp[p+]=t;
temp[]=a;
temp[]=;
temp[]=p+;
t=hash1(temp);
if(!hash_map[t])
{
hash_map[t]=;
memcpy(data[t],temp,sizeof(data[t]));
q.push(t);
}
}
}
}
int main()
{
char ch;
int i,j,t,p;
init();
while(cin.getline(s,))
{
j=;
for(i=;s[i]!='\0';i++)
{
if(s[i]==' ') continue;
sscanf(s+i,"%c",&ch);
if(ch=='x')
{
temp[j]=;
temp[]=j++;
}
else
temp[j++]=ch-'';
}
t=hash1(temp);
if(!hash_map[t])
puts("unsolvable");
else
{
for(i=t;i!=;i=data[i][])
print(data[i][]);
puts("");
}
}
return ;
}

以下的IDA*和A*都要用逆序数特判无解的情况,因为无解的时候IDA*直接无限制搜,A*遍历所有解空间,效率很低。

所谓逆序数判无解态是因为两个能够互相移动成的状态的逆序数的奇偶性是相同的。

IDA*(266ms),估价函数是“所有不为x的方块与目标位置的曼哈顿距离之和”,因为每次移动最多减少一点这个的值

 #include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> P;
int fac[]={,,,,,,,,,};
int dat[];
char s[];
char ans[];
int maxd;
int fx[]={,,,,,,,,,};
int fy[]={,,,,,,,,,};
bool fl;
int abs(int x)
{
if(x>) return x;
else return -x;
}
int h()
{
int ans=,i;
for(i=;i<;i++)
if(dat[i]!=)
ans+=abs(i/-fx[dat[i]])+abs(i%-fy[dat[i]]);
return ans;
}
int hash1(int s[])
{
int i,j,cnt,sum=;
for(i=;i<;i++)
{
cnt=;
for(j=i+;j<;j++)
if(s[j]<s[i])
cnt++;
sum+=cnt*fac[-i];
}
return sum;
}
bool inverse(int ss[])
{
int t=,x,y;
for(int i=;i<;i++)
for(int j=;j<i;j++)
{
if(ss[i]==||ss[j]==)continue;
x=ss[j];
y=ss[i];
if(x>y)
t++;
}
if(t&)
return true;
return false;
}
bool check()
{
for(int i=;i<;i++)
if(dat[i]!=i+)
return ;
return ;
}
void dfs(int now,int dep)
{
if(dep==maxd)
{
if(check()) fl=;
return;
}
if(h()+dep>maxd) return;
if(fl) return;
if(now%!=)
{
swap(dat[now],dat[now-]);
ans[dep]='l';
dfs(now-,dep+);
swap(dat[now],dat[now-]);
}
if(fl) return;
if(now%!=)
{
swap(dat[now],dat[now+]);
ans[dep]='r';
dfs(now+,dep+);
swap(dat[now],dat[now+]);
}
if(fl) return;
if(now>)
{
swap(dat[now],dat[now-]);
ans[dep]='u';
dfs(now-,dep+);
swap(dat[now],dat[now-]);
}
if(fl) return;
if(now<)
{
swap(dat[now],dat[now+]);
ans[dep]='d';
dfs(now+,dep+);
swap(dat[now],dat[now+]);
}
}
int main()
{
char ch;
int i,j,st;
while(cin.getline(s,))
{
memset(dat,,sizeof(dat));
j=;
for(i=;s[i]!='\0';i++)
{
if(s[i]==' ') continue;
sscanf(s+i,"%c",&ch);
if(ch=='x')
{
dat[j]=;
st=j++;
}
else
dat[j++]=ch-'';
}
if(inverse(dat))
{
printf("unsolvable");
goto xxx;
}
if(hash1(dat)==)
goto xxx;
fl=;
for(maxd=;!fl;++maxd)
dfs(st,);
for(i=;i<maxd;i++)
putchar(ans[i]);
xxx:
puts("");
}
return ;
}

A*(141ms),用了比较naive的估价函数,x与目标位置的曼哈顿距离

 #include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> P;
int fac[]={,,,,,,,,,};
bool hash_map[];
int dat[][];
priority_queue<P,vector<P>,greater<P> > q;
//dat[][9]存储上一个状态,dat[][10]存储到这个状态的操作,dat[][11]存储这个状态中9的位置,dat[][12]存储到这个状态的步数
char s[];
int h[]={,,,,,,,,};
int mem;
int hash1(int s[])
{
int i,j,cnt,sum=;
for(i=;i<;i++)
{
cnt=;
for(j=i+;j<;j++)
if(s[j]<s[i])
cnt++;
sum+=cnt*fac[-i];
}
return sum;
}
void print(int x)
{
if(dat[x][]==) return;
print(dat[x][]);
if(dat[x][]==)
putchar('l');
else if(dat[x][]==)
putchar('r');
else if(dat[x][]==)
putchar('u');
else putchar('d');
} bool inverse(int ss[])
{
int t=,x,y;
for(int i=;i<;i++)
for(int j=;j<i;j++)
{
if(ss[i]==||ss[j]==)continue;
x=ss[j];
y=ss[i];
if(x>y)
t++;
}
if(t&)
return true;
return false;
} int main()
{
char ch;
int i,j,a,b,t,p;
while(cin.getline(s,))
{
memset(dat,,sizeof(dat));
memset(hash_map,,sizeof(hash_map));
b=mem=;
j=;
for(i=;s[i]!='\0';i++)
{
if(s[i]==' ') continue;
sscanf(s+i,"%c",&ch);
if(ch=='x')
{
dat[b][j]=;
dat[b][]=j++;
}
else
dat[b][j++]=ch-'';
}
q.push(P(h[dat[b][]],b));
t=hash1(dat[b]);
hash_map[t]=true;
if(inverse(dat[b]))
{
printf("unsolvable");
goto xxx;
}
if(t==)
goto xxx;
while(!q.empty())
{
a=q.top().second;
q.pop();
p=dat[a][];
if(p!=&&p!=&&p!=)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p-];
dat[][p-]=t;
dat[][]=a;
dat[][]=;
dat[][]=p-;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h[dat[b][]],b));
}
}
if(p!=&&p!=&&p!=)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p+];
dat[][p+]=t;
dat[][]=a;
dat[][]=;
dat[][]=p+;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h[dat[b][]],b));
}
}
if(p>)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p-];
dat[][p-]=t;
dat[][]=a;
dat[][]=;
dat[][]=p-;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h[dat[b][]],b));
}
}
if(p<)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p+];
dat[][p+]=t;
dat[][]=a;
dat[][]=;
dat[][]=p+;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h[dat[b][]],b));
}
}
}
xxx:
puts("");
while(!q.empty()) q.pop();
memset(s,,sizeof(s));
}
return ;
}

A*(16ms),估价函数同IDA*

 #include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> P;
int fac[]={,,,,,,,,,};
bool hash_map[];
int dat[][];
priority_queue<P,vector<P>,greater<P> > q;
//dat[][9]存储上一个状态,dat[][10]存储到这个状态的操作,dat[][11]存储这个状态中9的位置,dat[][12]存储到这个状态的步数
char s[];
int fx[]={,,,,,,,,,};
int fy[]={,,,,,,,,,};
int abs(int x)
{
if(x>) return x;
else return -x;
}
int h(int b)
{
int ans=,i;
for(i=;i<;i++)
if(dat[b][i]!=)
ans+=abs(i/-fx[dat[b][i]])+abs(i%-fy[dat[b][i]]);
return ans;
}
int mem;
int hash1(int s[])
{
int i,j,cnt,sum=;
for(i=;i<;i++)
{
cnt=;
for(j=i+;j<;j++)
if(s[j]<s[i])
cnt++;
sum+=cnt*fac[-i];
}
return sum;
}
void print(int x)
{
if(dat[x][]==) return;
print(dat[x][]);
if(dat[x][]==)
putchar('l');
else if(dat[x][]==)
putchar('r');
else if(dat[x][]==)
putchar('u');
else putchar('d');
} bool inverse(int ss[])
{
int t=,x,y;
for(int i=;i<;i++)
for(int j=;j<i;j++)
{
if(ss[i]==||ss[j]==)continue;
x=ss[j];
y=ss[i];
if(x>y)
t++;
}
if(t&)
return true;
return false;
} int main()
{
char ch;
int i,j,a,b,t,p;
while(cin.getline(s,))
{
memset(dat,,sizeof(dat));
memset(hash_map,,sizeof(hash_map));
b=mem=;
j=;
for(i=;s[i]!='\0';i++)
{
if(s[i]==' ') continue;
sscanf(s+i,"%c",&ch);
if(ch=='x')
{
dat[b][j]=;
dat[b][]=j++;
}
else
dat[b][j++]=ch-'';
}
q.push(P(h(b),b));
t=hash1(dat[b]);
hash_map[t]=true;
if(inverse(dat[b]))
{
printf("unsolvable");
goto xxx;
}
if(t==)
goto xxx;
while(!q.empty())
{
a=q.top().second;
q.pop();
p=dat[a][];
if(p!=&&p!=&&p!=)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p-];
dat[][p-]=t;
dat[][]=a;
dat[][]=;
dat[][]=p-;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h(b),b));
}
}
if(p!=&&p!=&&p!=)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p+];
dat[][p+]=t;
dat[][]=a;
dat[][]=;
dat[][]=p+;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h(b),b));
}
}
if(p>)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p-];
dat[][p-]=t;
dat[][]=a;
dat[][]=;
dat[][]=p-;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h(b),b));
}
}
if(p<)
{
memcpy(dat[],dat[a],sizeof(dat[]));
t=dat[][p];
dat[][p]=dat[][p+];
dat[][p+]=t;
dat[][]=a;
dat[][]=;
dat[][]=p+;
dat[][]=dat[p][]+;
t=hash1(dat[]);
if(hash_map[t]==false)
{
if(t==)
{
print();
goto xxx;
}
hash_map[t]=true;
b=++mem;
memcpy(dat[b],dat[],sizeof(dat[b]));
q.push(P(dat[b][]+h(b),b));
}
}
}
xxx:
puts("");
while(!q.empty()) q.pop();
memset(s,,sizeof(s));
}
return ;
}

A*(79ms),假的估价函数(fx,fy前面少加了一个0)

int fx[]={,,,,,,,,};
int fy[]={,,,,,,,,};

Eight POJ - 1077 HDU - 1043 八数码的更多相关文章

  1. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  2. POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...

  3. HDU 1043 八数码(八境界)

    看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...

  4. HDU 1043 八数码问题的多种解法

    一.思路很简单,搜索.对于每一种状态,利用康托展开编码成一个整数.于是,状态就可以记忆了. 二.在搜索之前,可以先做个优化,对于逆序数为奇数的序列,一定无解. 三.搜索方法有很多. 1.最普通的:深搜 ...

  5. HDU 1043 八数码 Eight A*算法

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. POJ 1077 HDU 1043 Eight (IDA*)

    题意就不用再说明了吧......如此经典 之前想用双向广搜.a*来写,但总觉得无力,现在用IDA*感觉其他的解法都弱爆了..............想法活跃,时间,空间消耗很小,给它跪了 启发式搜索关 ...

  7. Eight hdu 1043 八数码问题 双搜

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. hdu 1043 八数码问题

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  9. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

随机推荐

  1. Meteor ToDo App实例

    在本章中,我们将创建一个简单的待办事项应用程序. 第1步 - 创建应用程序 打开命令提示符,运行以下命令 - C:\Users\Administrator\Desktop>meteor crea ...

  2. 【Nginx】Hello world程序

    模块如何在运行中生效 配置文件中的location块决定了匹配某种URL的请求将会由相应的HTTP模块处理,因此,运行时HTTP框架会在接收完毕HTTP请求的头部后,将请求的URL与配置文件中的所有l ...

  3. [转]JavaEE开发基础

    JavaEE开发基础 1 JavaEE简介 Java平台有三个版本,分别是JavaSE(Java Platform, Standard Edition),JavaEE(Java Platform, E ...

  4. 学习Centos 7的笔记

    Step-1 yum install epel-release && yum clean all && yum update –y &&  yum -y ...

  5. Office EXCEL 如何设置最大行高

    对于单个单元格行来说,行高必须在0-409之间   但是如果合并了两个单元格,则行高就扩展了一倍,不止409,而是两倍的409.

  6. Codeforces Round #135 (Div. 2)---A. k-String

    k-String time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  7. 使用VLC搭建视频直播服务器

    去年我们信息之夜我们进行过视频直播服务,当时我们使用了WMS(Windows Media Server)实现了这个服务,但是编码是微软的WMV,因而像iPhone/Android这样的智能手机无法观看 ...

  8. 【iOS系列】-iOS查看沙盒文件图文教程(真机+模拟器)

    [iOS系列]-iOS查看沙盒文件图文教程(真机+模拟器) 1:模拟器 1.1 方法1: 程序中打印一下的地址,能直接前往沙盒路径. NSString *path = [NSSearchPathFor ...

  9. iOS开发——高级篇——多线程GCD死锁

    面试题 请问以下代码打印结果: - (void)interview01 { // 以下代码是在主线程执行的 NSLog(@"执行任务1"); dispatch_queue_t qu ...

  10. 移动端和PC端有什么区别

    1.PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性,因为目前不管是android手机还是ios手机,一般浏览器使用的都是webkit内核,所以说做移动端开发,更多考虑的应该是手机分辨 ...