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. Defcon 23最新开源工具NetRipper代码分析与利用

    0×01 研究背景 在分析了俄罗斯人被曝光的几个银行木马的源码后,发现其大多均存在通过劫持浏览器数据包来获取用户个人信息的模块,通过截获浏览器内存中加密前或解密后的数据包来得到数据包的明文数据.在De ...

  2. 当Eclipse爱上SVN

    推荐使用:Subclipse  :http://jingyan.baidu.com/article/1612d5007d41e9e20e1eeeff.html 为离线安装做准备: 1.下载Subver ...

  3. LightOj 1027 A Dangerous Maze【概率】

    题目链接:http://www.lightoj.com/volume_showproblem.php? problem=1027 题意: 你面前有n个门,每一个相应一个数字,若为正xi.代表xi分钟后 ...

  4. map集合排序

    默认情况下,HashMap.HashTable.TreeMap.LinkedHashMap的排列顺序比较: package com.per.sdg.demo; import java.util.Has ...

  5. Jenkins系列之-—03 修改Jenkins用户的密码

    一.Jenkins修改用户密码 Jenkins用户的数据存放在JENKINS_HOME/users目录. 1. 打开忘记密码的用户文件夹,里面就一个文件config.xml.打开并找到<pass ...

  6. MyEclipse搭建SSH(Struts2+Spring2+Hibernate3)框架项目教程

    对Struts.spring.hibernate大体上了解一遍后,就是针对这个几个框架的整合了. 怎样整合,请看以下: 第一:Struts2的jar和xml配置文件: jar包: commons-fi ...

  7. LeetCode题解汇总

    陆续更新至github... https://github.com/OliveLv/LeetCode/ 

  8. 《coredump问题原理探究》Linux x86版7.9节list相关的iterator对象

    这一节.看一下list的iterator对象在内存的布局 1 #include <list> 2 3 void init( std::list<int>& lst ) ...

  9. angularjs学习之六(angularjs中directive指令的一般编程事件绑定 模板使用等)

    angular js 中模板的使用.事件绑定以及指令与指令之间的交互 相应教学视频地址(需FQ):v=aG8VD0KvUw4">angularjs教学视频 <!doctype h ...

  10. 【iOS系列】-iOS中内存管理

    iOS中创建对象的步骤: 1,分配内存空间,存储对象 2,初始化成员变量 3,返回对象的指针地址 第一:非ARC机制: 1,对象在创建完成的同时,内部会自动创建一个引用计数器,是系统用来判断是否回收对 ...