poj 1077 Eight (bfs A* IDA*)
2011-06-06 21:07
375 查看
第一次写A*算法 写的有点晕,思路还是很明显很清晰的 就是处理起来有些麻烦 ,自己写了一个堆,可以说是优先队列,网上也有看到用STL的priority_queue的 以后研究下.
今天写了一天,毕竟第一次接触A*算法,第一次写,算是我的处女作,不过结果没让我失望 1A了,结果16Ms 还挺快,提交第二次就成0ms了,这就看运气. F=G+H, 就是A*算法的精华所在了 每次都取F最小的,这样是最有可能到达结果的, 因为在程序运行过程中 要更新那些已经在堆中的元素的F值,所以自己写堆也就方便了这一点,不用浪费空间,把重复的状态再加入优先队列里.因为更改了堆中的某个节点,就只要像新插入一个节点那样,跟他的父节点比较,把自己提升到正确的位置,当然,前提是要知道自己要更新的节点在堆中的什么位置,这也就要position[k] 来记录状态k在堆中的位置, 改变位置时要更新position的值.
总之,今天还是有很大收获的...........................不过以后如果再写,估计还要花上半天时间,自己的思维经常乱啊...ps:今天端午节... orz..我是菜鸟...
还有一双向广搜 方法:::http://blog.csdn.net/dizem/archive/2009/08/12/4436663.aspx
IDA* 刚刚看了一下, 貌似是迭代加深搜索 加了一个估值函数,具体也没怎么了解 照着别人的程序写的.
只能说数据太....没有unsolvable的情况 否则肯定TLE了, 搜索深度到40就已经慢的不行了,更别说100 跳出循环了....
今天写了一天,毕竟第一次接触A*算法,第一次写,算是我的处女作,不过结果没让我失望 1A了,结果16Ms 还挺快,提交第二次就成0ms了,这就看运气. F=G+H, 就是A*算法的精华所在了 每次都取F最小的,这样是最有可能到达结果的, 因为在程序运行过程中 要更新那些已经在堆中的元素的F值,所以自己写堆也就方便了这一点,不用浪费空间,把重复的状态再加入优先队列里.因为更改了堆中的某个节点,就只要像新插入一个节点那样,跟他的父节点比较,把自己提升到正确的位置,当然,前提是要知道自己要更新的节点在堆中的什么位置,这也就要position[k] 来记录状态k在堆中的位置, 改变位置时要更新position的值.
总之,今天还是有很大收获的...........................不过以后如果再写,估计还要花上半天时间,自己的思维经常乱啊...ps:今天端午节... orz..我是菜鸟...
还有一双向广搜 方法:::http://blog.csdn.net/dizem/archive/2009/08/12/4436663.aspx
#include <iostream> #include<cstdio> #include<cstdlib> using namespace std; #define N 370000 #define M 10 int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 }; struct Node { int val,h,steps; //val即f , h为估值 ,steps为g . f=g+h; int pos; //0的位置 int id; //id 状态值 即哈希值 通过get_hash函数得到的 与状态一一对应的值 char p[M]; //当前状态; }; int mark[10][2]; //用于求估值,即 值i应该在( mark[i][0],mark[i][1])的位置; 3*3的坐标 char reflect[]="urdl"; //求方向 void print_ans(int t); //输出结果 int heapsize=1; //堆的当前大小; Node priority_que ; //堆 优先队列 int position ; int direction ; int pre ; int used ; //position[k] id值为k的状态在堆中的位置 int dirx[]={-1,0,1,0}; int diry[]={0,1,0,-1}; //direction[k] 存0-3表示id为k的状态是由其father pre[k] //按照direction[k]的方向变换得到的 used[k]为0 1 2分别代表 int res_id; //状态k没出现过 ,已经在堆中 和已经LOCK(pop)了 int bfs(); int get_val(char *p); // 计算估值的函数 int get_hash(char *p); //计算id的函数 //堆的操作 void heap_shift_down(int pos); void heap_shift_up(Node tar,int pos); void heap_insert(Node n,int &heapsize); Node heap_pop(); void swap(int x,int y); int main() { freopen("in.txt","r",stdin); for(int i=1;i<9;i++) { mark[i][0]=(i-1)/3; mark[i][1]=(i-1)%3; } // priority_que从1开始 for(int i=0;i<9;i++) { cin>>priority_que[1].p[i]; if(priority_que[1].p[i]=='x') { priority_que[1].pos=i; priority_que[1].p[i]='0'; } } char res[]="123456780"; res_id=get_hash(res); if(bfs()) print_ans(res_id); else cout<<"unsolvable"<<endl; } int bfs() { int rank; int id=get_hash(priority_que[1].p); position[id]=1; pre[id]=-1; used[id]=1; if(id==res_id) return id; priority_que[1].id=id; priority_que[1].steps=0; priority_que[1].h=get_val(priority_que[1].p); priority_que[1].val=priority_que[1].h; while(heapsize>0) { Node tmp=heap_pop(); used[tmp.id]=2; //标记为 LOCK int tx=tmp.pos/3; //0位置坐标 int ty=tmp.pos%3; for(int i=0;i<4;i++) //四个方向 { Node newnode; //newnode是pop出来的状态tmp按四个方向 int x=tx+dirx[i]; //拓展出来的新状态 int y=ty+diry[i]; if(x>=0&&x<3&&y>=0&&y<3){ newnode=tmp; int tt=x*3+y; newnode.p[tmp.pos]=newnode.p[tt]; newnode.p[tt]='0'; newnode.pos=tt; rank=get_hash(newnode.p); newnode.id=rank; newnode.steps++; if(used[rank]==0) { used[rank]=1; direction[rank]=i; pre[rank]=tmp.id; newnode.h=get_val(newnode.p); newnode.val=newnode.h+ newnode.steps; heap_insert(newnode,heapsize); if(used[res_id]==1) return res_id; } else if(used[rank]==1) { int pos=position[rank]; //找到状态在 堆中的位置,更新val, steps值以及pre等 int step=priority_que[pos].steps; if(step>tmp.steps+1) { priority_que[pos].steps= tmp.steps+1; priority_que[pos].val=priority_que[pos].h+priority_que[pos].steps; pre[rank]=tmp.id; direction[rank]=i; heap_shift_up(priority_que[pos],pos); //小顶堆中的值被Decrease之后 //要用shift_up维护堆,把它调到适当的 //位置 } } } } } return 0; } Node heap_pop() { Node t=priority_que[1]; priority_que[1]=priority_que[heapsize]; position[priority_que[1].id]=1; heapsize--; if(heapsize>0) { heap_shift_down(1); } return t; } void heap_shift_up(Node tar,int pos) { int cur=pos; while(cur/2>=1&&priority_que[cur/2].val>tar.val) { priority_que[cur]=priority_que[cur/2]; position[priority_que[cur].id]=cur; //更新position cur/=2; } priority_que[cur]=tar; position[priority_que[cur].id]=cur; return ; } void heap_insert(Node n,int &heapsize) { heapsize++; priority_que[heapsize]=n; heap_shift_up(n,heapsize); return ; } void heap_shift_down(int pos) { int l=2*pos; int r=l+1; int min_pos=pos; if(l<=heapsize&&priority_que[l].val<priority_que[min_pos].val) min_pos=l; if(r<=heapsize&&priority_que[r].val<priority_que[min_pos].val) min_pos=r; if(min_pos!=pos){ swap(min_pos,pos); heap_shift_down(min_pos); } } void swap(int x,int y) //在元素交换过程中要更新position; { Node tmp=priority_que[x]; priority_que[x]=priority_que[y]; position[priority_que[x].id]=x; priority_que[y]=tmp; position[priority_que[y].id]=y; } int get_hash(char *p) { int cnt=0; int total=0; for(int i=0;i<9;i++){ cnt=0; for(int j=i+1;j<9;j++) { if(p[j]<p[i]) cnt++; } total+=fac[8-i]*(cnt); } return total; } int get_val(char *p) //估值函数 { int x,y; int t;int total=0; for(int i=0;i<9;i++) { x=i/3; y=i%3; t=p[i]-'0'; if(t!=0) { total+=abs(x-mark[t][0])+abs(y-mark[t][1]); } } return total; } void print_ans(int t) { char tt[1000]; int k=0; while(pre[t]!=-1) { tt[k++]=reflect[direction[t]]; t=pre[t]; } for(int x=k-1;x>=0;x--) cout<<tt[x]; cout<<endl; return ; }
IDA* 刚刚看了一下, 貌似是迭代加深搜索 加了一个估值函数,具体也没怎么了解 照着别人的程序写的.
只能说数据太....没有unsolvable的情况 否则肯定TLE了, 搜索深度到40就已经慢的不行了,更别说100 跳出循环了....
#include <iostream> #include<cstdio> #include<cstdlib> using namespace std; #define N 370000 #define M 10 struct Node { char p[M]; int h; int pos; }; int dirx[]={-1,0,1,0}; int diry[]={0,1,0,-1}; int mark[10][2]; char dir[]="urdl"; int get_h(char *p); Node node; int IDA(Node & p,int h,int pre); int max_height; int direction[100]; int cnt=0; int main() { freopen("in.txt","r",stdin); for(int i=1;i<9;i++) { mark[i][0]=(i-1)/3; mark[i][1]=(i-1)%3; } for(int i=0;i<9;i++) { cin>>node.p[i]; if(node.p[i]=='x') { node.pos=i;node.p[i]='0'; } } node.h=get_h(node.p); int done=0; for(int i=node.h;i<100;i++) { max_height=i; if(IDA(node,0,-1)) { done=1;break; } } cnt-=1; if(done) { while(cnt>=0) cout<<dir[direction[cnt--]]; cout<<endl; } else cout<<"unsolvable"<<endl; } int IDA(Node & p,int h,int pre) { if(p.h==0) { return 1; } if(h+p.h>max_height) return 0; for(int i=0;i<4;i++) { if(abs(pre-i)==2) continue; int pos=p.pos; N 9b62 ode tmp=p; int tmpx=pos/3+dirx[i]; int tmpy=pos%3+diry[i]; if(tmpx<0||tmpx>=3||tmpy<0||tmpy>=3) continue; int k=3*tmpx+tmpy; tmp.p[pos]=tmp.p[3*tmpx+tmpy]; tmp.p[3*tmpx+tmpy]='0'; tmp.pos=3*tmpx+tmpy; int val=p.p[k]-'0'; if((i==0||i==2)&&abs(tmpx-mark[val][0])>abs(pos/3-mark[val][0])) tmp.h=p.h-1; else if((i==1||i==3)&&abs(tmpy-mark[val][1])>abs(pos%3-mark[val][1])) tmp.h=p.h-1; else tmp.h=p.h+1; if(IDA(tmp,h+1,i)) { direction[cnt++]=i; return 1; } } return 0; } int get_h(char *p) { int x,y; int t;int total=0; for(int i=0;i<9;i++) { x=i/3; y=i%3; t=p[i]-'0'; if(t!=0) { total+=abs(x-mark[t][0])+abs(y-mark[t][1]); } } return total; }
相关文章推荐
- 搜索 ( 八数码问题详解:BFS,A*,IDA* )——Eight ( POJ 1077 )
- poj 1077 & hdu 1043 Eight ( 多种解法:预处理、bfs、dbfs、IDA*、A*)
- POJ - 1077 Eight : 八数码 -- 哈唏 康托展开 双向bfs A* IDA*
- POJ 1077 Eight(康拓展开 BFS 双向BFS)
- 八数码[POJ-1077 | HDU-1043] BFS A* IDA* 双广
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- poj 1077 Eight 八数码问题( 康拓展开+BFS状态压缩)
- POJ 1077 Eight BFS -
- poj 1077-Eight(八数码+逆向bfs打表)
- hdu 1043 eight(poj 1077) (bfs)
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
- POJ 1077 Eight 八数码问题 BFS
- poj 1077--Eight(八数码问题,BFS,A*,全排列的哈希)
- POJ 1077 Eight(DFS + IDA*)
- POJ 1077 Eight(BFS Hash)
- HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)
- POJ 1077 Eight(BFS八数码问题)
- HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)
- POJ 1077 Eight(BFS:输出路径)
- POJ 1077 Eight & HDU 1043 Eight(康托展开+BFS)