我个人对这个搜索的理解就是以BFS的思想写DFS。
具体来说就是,首先深度优先搜索k层,若没有找到可行解,再深度优先搜索k+1层,直到找到可行解为止。由于深度是从小到大逐渐增大的,所以当搜索到结果时可以保证搜索深度是最小的。这也是迭代加深搜索在一部分情况下可以代替广度优先搜索的原(还比广搜省空间)。
前提:
题目一定要有解,否则会无限循环下去。
好处:
1.时间复杂度只比BFS稍差一点(虽然搜索k+1层时会重复搜索k层,但是整体而言并不比广搜慢很多)。
2.空间复杂度与深搜相同,却比广搜小很多。
3.利于剪枝。
使用搜索算法的时候,选择正确的搜索方式很重要。当有一类问题需要做广度优先搜索,但却没有足够的空间,而时间却很充裕,碰到这类问题,我们可以选择迭代加深搜索算法。
剪枝操作:
使用迭代加深搜素时没有剪枝操作时,时间开销是非常大的(因为迭代加深搜索是通过限制每次dfs的最大深度进行的搜索。令maxd表示最大的搜索深度,那么dfs就只能在0~maxd之间来进行,如果在这个范围内找到了解,就退出大循环,否则maxd++,扩大搜索范围。所以可想而知,倘若没有高效及时的退出无解的情况,那么时间上的开销也是会比较大的。)
如何及时的退出无解情况呢?这里引入乐观估计函数。
乐观估计函数:从当前深度到找到最终的解“至少”还需要多少步,或者距离找到最终的解还需要扩展多少层。如果超出了当前限制的深度maxd,说明当前限制的最大深度下是不可能找到解的,直接退出。(这个函数你只需要乐观的去构造就行了)
题解: https://lo-li.net/1363.html#comment-737
Description
AveryBoy最近迷上了旋转游戏。旋转游戏使用#形板,可以容纳24块方块(见图)。这些块标有数字1,2和3,每种正好有8个。
最初块随放在板子上,你的目标是移动块,使放置在中心方块的八个块具有相同的符号标记。只有一种类型的有效移动,即旋转四条线中的一条,每条线由七个块组成。也就是说,线中的六个块向头部移动一个块,并且头块移动到线的末端。八个可能的移动用大写字母A到H标记。图示出了两个连续的移动,移动A和移动C。
Input
输入包含不超过30个测试用例。每个测试用例只有一行包含24个数字,这些数字是初始配置中块的符号。块的行从上到下列出。对于每一行,块从左到右列出。数字用空格分隔。例如,样例输入中的第一个测试用例对应于图中的初始配置。案件之间没有空行。在结束输入的最后一个测试用例之后,有一行包含单个“0”。
Output
对于每个测试用例,您必须输出两行。第一行包含达到最终配置所需的所有动作。每个动作都是一个字母,从“A”到“H”,并且行中的字母之间不应有任何空格。如果不需要移动,则输出“No moves needed”。在第二行中,您必须在这些移动后输出中心方块中的块数字。如果有多种可能的解决方案,则必须输出使用最少移动次数的解决方案。如果仍有多个可能的解决方案,则必须输出字典顺序中最小的解决方案。不需要在案例之间输出空行。
Sample Input
1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 0Sample Output
AC 2 DDHH 2HINT
#include
using namespace std;
bool flag=false;
char finop[20];
int reverseop[9]={5,4,7,6,1,0,3,2,-1};
int mp[24];
int pos[8][7]=
{
{ 0,2,6,11,15,20,22 }, //A
{ 1,3,8,12,17,21,23 }, //B
{ 10,9,8,7,6,5,4 }, //C
{ 19,18,17,16,15,14,13 }, //D
{ 23,21,17,12,8,3,1 }, //E
{ 22,20,15,11,6,2,0 }, //F
{ 13,14,15,16,17,18,19}, //G
{ 4,5,6,7,8,9,10 } //H
};
int center[8]={6,7,8,11,12,15,16,17};
void option(int op)
{
int temp=mp[pos[op][0]];
for (int i=0;i<6;i++)
{
mp[pos[op][i]]=mp[pos[op][i + 1]];
}
mp[pos[op][6]]=temp;
}
bool cmp(int a,int b)
{
return a>b;
}
int get_h()
{
int cnt[3]={0,0,0};
for (int i = 0; i < 8; i++)
{
cnt[mp[center[i]] - 1]++;
}
sort(cnt,cnt+3,cmp);
return 8-cnt[0];
}
void dfs(int depth,int lastop,int maxdepth)
{
if(flag)
return;
if(depth>maxdepth||depth+get_h()>maxdepth)
return;
if(get_h()==0)
{
flag=true;
finop[depth]='\0';
cout<>mp[i];
if(i==0)
{
if(mp[i]==0)
return 0;
}
}
if(!get_h())
{
cout<<"No moves needed"<