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. 解决WIN7下VMWARE虚拟机无法上网问题

    一.Win7 虚拟机centos NAT联网 链接地址:http://www.cr173.com/html/19808_1.html,也不知道是哪位大神弄的,实践过,可以使用,但是重启之后却不能用了, ...

  2. 【Mongodb教程 第十四课 】MongoDB 投影

    mongodb 投影意思是只选择必要的数据而不是选择一个文件的数据的整个.如果一个文档有5个字段,需要显示只有3个,然后选择其中只有3个字段. find() 方法 MongoDB 的find()方法, ...

  3. web编程非常实用的在线工具大全

    目前,不管是前端开发人员还是个人站长,经常需要一些代码处理类的工具,比如:代码对比.代码格式化.图标制作等.有时就是一时急用可电脑上又没有安装相关的软件,这里为大家收集了一些我们经常会用到的在线工具. ...

  4. 浅谈JavaScript的面向对象程序设计(三)

    前面已经对JavaScript的面向对象程序设计作了简单的介绍,包括了对象的属性.对象的工厂模式.构造函数和原型等.通过介绍,这些创建对象的方法依然有不少优化和改进的地方. 组合使用构造函数模式和原型 ...

  5. iOS 配置支付宝

    尽管非常easy,可是对于第一次接触支付宝配置的啊猿.有些细节摸不着头脑.今天就来写一个流程配置. 1.创建一个project,然后再创建一个目录,把支付宝sdk要用到的都拖到目录中.然后拖到proj ...

  6. Hackrank Equal DP

    Christy is interning at HackerRank. One day she has to distribute some chocolates to her colleagues. ...

  7. IntelliJ IDEA jrebel6 安装,破解

    一.Setting中在线安装JRebel插件,install 二.拷贝下载的jrebel.rar解压后 把里面内容覆盖IDEA插件安装目录中此插件目录之下 下载:http://pan.baidu.co ...

  8. PS人物脸部去高光简单之法

    案例素材图: 方法原理步骤:得到高光面的选区,然后吸取高光面附近的颜色填充上去,这样就达到了去高光的效果. 得到高光选区的方法有很多种,要提取这种选区,通过阿尔法通道是最合适不过的了,本案例就通过阿尔 ...

  9. ranlib

    1 ranlib的缩写 random access library 2 ranlib的作用 为静态库的符号建立索引,可以加速链接,因此称用ranlib处理过的library为random access ...

  10. linux php nginx php-fpm 关系 动态进程生成

    yum install php yum install php-fpm 启动fpm [root@VM_141_64_centos html]# service php-fpm restart Redi ...