bzoj1085 [SCOI2005]骑士精神 【迭代加深搜索】
2017-09-06 21:35
435 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1085
估价函数least(v)表示从当前状态v到目标状态所需的最小步数,显然是还未归位的棋子数减一;
首先枚举所需步数dep,再dfs,若step(v)+least(v)>dep则跳过。
其实迭代加深搜索就是dfs的一种剪枝,这个算法特别擅长处理解的深度不大,但每个搜索局面后继较多,且局面容易进行估价的搜索问题。
也可以用折半搜索做;
解题思路
很容易想到广搜,但空间会超,而深搜又会超时,所以我们用迭代加深搜索,它比广搜慢,比深搜快,但空间和深搜一样,所以可以接受。估价函数least(v)表示从当前状态v到目标状态所需的最小步数,显然是还未归位的棋子数减一;
首先枚举所需步数dep,再dfs,若step(v)+least(v)>dep则跳过。
其实迭代加深搜索就是dfs的一种剪枝,这个算法特别擅长处理解的深度不大,但每个搜索局面后继较多,且局面容易进行估价的搜索问题。
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> using namespace std; const char des[5][5]={'1','1','1','1','1', '0','1','1','1','1', '0','0','*','1','1', '0','0','0','0','1', '0','0','0','0','0'}; const int fx[8]={-1,-2,-2,-1,1,2,2,1}; const int fy[8]={2,1,-1,-2,-2,-1,1,2}; char a[5][5]; int T,dep,tx,ty; int least() { int res=-1; for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(a[i][j]!=des[i][j])res++; return res; } bool dfs(int step,int x,int y) { if(step==dep) { if(least()==-1)return true; else return false; } if(step+least()>dep)return false; for(int i=0;i<8;i++) { int dx=x+fx[i],dy=y+fy[i]; if(dx>=0&&dx<5&&dy>=0&&dy<5) { swap(a[x][y],a[dx][dy]); if(dfs(step+1,dx,dy))return true; swap(a[x][y],a[dx][dy]); } } return false; } int main() { //freopen("lx.in","r",stdin); scanf("%d",&T); while(T--) { for(int i=0;i<5;i++) { scanf("%s",a[i]); for(int j=0;j<5;j++) if(a[i][j]=='*')tx=i,ty=j; } for(dep=0;dep<=15;dep++) if(dfs(0,tx,ty))break; if(dep>15)cout<<-1<<'\n'; else cout<<dep<<'\n'; } return 0; }
也可以用折半搜索做;
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<ctime> #include<map> #define ll unsigned long long using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')c=getchar(),f=-1; for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int des[5][5]={2,2,2,2,2, 1,2,2,2,2, 1,1,0,2,2, 1,1,1,1,2, 1,1,1,1,1}; const int fx[8]={-1,-2,-2,-1,1,2,2,1}; const int fy[8]={2,1,-1,-2,-2,-1,1,2}; struct node { int a[5][5]; int x,y,tp,step; }; map<ll,int>book[2]; queue<node>q; char a[5][5]; ll hash(node t) { ll res=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) res=res*3+t.a[i][j]; return res; } int bfs(node s,node t) { while(!q.empty())q.pop(); book[0].clear(),book[1].clear(); s.tp=0,t.tp=1; s.step=t.step=0; q.push(s),q.push(t); while(!q.empty()) { node x,a; a=q.front(); q.pop(); ll tmp=hash(a); if(book[a.tp^1].count(tmp)) if(book[a.tp^1][tmp]+a.step<=15) return book[a.tp^1][tmp]+a.step; else continue; if(a.step>=8)continue; for(int i=0;i<8;i++) { x=a; x.x+=fx[i],x.y+=fy[i]; if(x.x<0||x.x>=5||x.y<0||x.y>=5)continue; swap(x.a[x.x][x.y],x.a[a.x][a.y]); tmp=hash(x); if(book[x.tp][tmp])continue; book[x.tp][tmp]=++x.step; q.push(x); } } return -1; } int main() { //freopen("lx.in","r",stdin); node s,t; int T=getint(); while(T--) { for(int i=0;i<5;i++) { scanf("%s",a[i]); for(int j=0;j<5;j++) { if(a[i][j]=='*')s.x=i,s.y=j,s.a[i][j]=0; else s.a[i][j]=a[i][j]-'0'+1; t.a[i][j]=des[i][j]; } } t.x=t.y=2; int ans=bfs(s,t); cout<<ans<<'\n'; } return 0; }
相关文章推荐
- 【bzoj1085】【 [SCOI2005]骑士精神】启发式剪枝+迭代加深搜索
- 【bzoj1085】【 [SCOI2005]骑士精神】启发式剪枝+迭代加深搜索
- BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]
- bzoj1085 [SCOI2005]骑士精神 ( 迭代加深搜索 + A*启发式搜索 )
- BZOJ.1085.[SCOI2005]骑士精神(迭代加深搜索)
- [SCOI2005][BZOJ1085][迭代加深+A*剪枝]骑士精神
- BZOJ 1085: [SCOI2005]骑士精神 启发式搜索+迭代加深
- BZOJ-1085 SCOI 2005 骑士精神 迭代加深 A*爆搜
- BZOJ 1085 [SCOI2005]骑士精神 A*搜索
- BZOJ 1085 [SCOI2005]骑士精神 A* 搜索
- [BZOJ 1085][SCOI 2005]骑士精神(IDA*搜索)
- [BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]
- 【BZOJ1085】【SCOI2005】骑士精神 [A*搜索]
- 【BZOJ1085】[SCOI2005]骑士精神【搜索】【剪枝】
- bzoj 1085: [SCOI2005]骑士精神
- 【bzoj1085】[SCOI2005]骑士精神
- bzoj 1085: [SCOI2005]骑士精神(IDA*)
- [bzoj1085][SCOI2005]骑士精神
- bzoj1085: [SCOI2005]骑士精神
- bzoj 1085: [SCOI2005]骑士精神