Search Advanced iterative deepening search

Iterative deepening search

First of all, don't be afraid of this thing. In fact, I just started to learn this search, and I think it's very tall and confusing terms. In fact, the idea and essence of iterative deepening search is to control the dfs of search depth, but it can achieve the effect of extensive search. Its search state is infinite many kinds, the depth may be infinite deep, the width may also be infinite wide. When you use deep search, it will time out. When you use wide search, the queue will spiral. Then you need to deepen the previous iteration.

For example, you can find the smallest solution to such a problem. (usually, the problem of iterative deepening search has solutions, only the size of the solution). How to write this? In fact, deep search controls the depth. The search process is to search all cases with a depth of 1 first to see if the final goal can be achieved. If the final goal can be achieved, end the search. If you can't continue to increase the depth you can search, but the results of all previous searches will not be saved. The next time you add 1 to the depth, you can continue to search from the beginning. Although it seems that you have done a lot of repeated things, it's not true. When you search the depth of the K, all the situations of the previous k-1 depth are not worth mentioning. That's why the iteration deepening will not exceed the memory like the extensive search. If it exceeds the memory, you can call me ~ ~ and the time is not much slower than the extensive search.

Application scenario

1. When you have enough time to find the problem, and the memory may not be able to meet the n-many states you expand when searching.

2. In general, the problem has solutions and there may be multiple solutions for you to find the optimal solution.

3. Use it if you want~~

Classic examples

Iterating to deepen the first question of introduction - Egypt score
Egyptian score, which has no title connection, is a classic example of iterative and deep search. The title requirement is to give a score so that you can divide the score into the sum of several scores, and the molecules of these scores are all 1. The number of fractions is as small as possible, and the smallest fraction is as large as possible, that is to say, the smaller the denominator of the smallest fraction, the better. This is a typical example of iterative search deepening.
Finally, it is important to pay attention to pruning. The meaning of a i > = B (maxd-d+1): A / b > = (maxd-d+1)/i; why do you judge this? Because we know that the denominator of the fraction is getting larger and larger. At the current depth, the minimum denominator is i, and the later denominator is getting larger and larger. It is impossible to be i. therefore, if we assume that the denominator of every step after the current depth is i, we also need maxd-d+1 same molecule, which obviously does not exist. Because the denominator is getting larger and smaller, even if the limit value of all the scores behind you is 1/i, all of them add up to only (maxd-d+1)/i. if the remaining scores of the current fraction are greater than or equal to the limit value of this scaling, then there must be no solution to this depth.

//Pay attention to long long, and prevent explosion when multiplying
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
ll s[100],v[100];
ll gcd(ll a,ll b)			//gcd reduction operand
{
	while(b){
		ll t = a%b;
		a = b;
		b = t;
	}
	return a;
} 
bool better(int d)			//Compare with previous comparison results
{
	for(int i = d;i >= 0;i--){
		if(s[i] != v[i]){
			if(s[i] == -1 || s[i] > v[i]){		//Judge whether the current v is better than the previous s
				return true;	//Judging from the back is more intuitive, because many denominators in the front are the same, and judging from the back to the front is faster
			}
			else{
				return false;
			}
		}
	}
	return false;
}
bool iddfs(int d,int maxd,ll from,ll a,ll b)
{
	if(d == maxd){			//Maximum depth reached
		if(b%a){			//When the last fraction a/b can not be approximately divided into molecules of 1
			return false;
		}
		v[d] = b/a;
		if(better(d)){		
			memcpy(s,v,sizeof(ll)*(d+1));			//Copy d+1 fraction denominator, equivalent to the following cycle
	//		for(int i = 0;i <= d;i++){
	//			s[i] = v[i];
	//		}
		}
		return true;
	}
	from = max(from,b/a+1);						//Start operation of taking larger point
	bool flag = false;
	for(int i = from;;i++){			
		if(a*i >= b*(maxd-d+1)){			//	a/b >= (maxd-d+1)/i;
			break;				//One of the most important pruning techniques is the mathematical expansion and contraction method
		}
		v[d] = i;
		ll na = a*i - b;					//New molecules 
		ll nb = b*i;						//New denominator 
		ll g = gcd(na,nb);					//Maximum common divisor, try to reduce the range of a and B, so as to prevent exceeding
		if(iddfs(d+1,maxd,i+1,na/g,nb/g)){
			flag = true;
		}
	}
	return flag;
}
int main()
{
	freopen("C:\\Users\\Administrator\\Desktop\\input.txt","r",stdin);
	freopen("C:\\Users\\Administrator\\Desktop\\output2.txt","w",stdout);
	int a,b;
	while(cin>>a>>b){
		memset(v,0,sizeof(v));
		int d;
		for(d = 1;d <= 100;d++){					//The maximum depth of 100 is already very large.
			memset(s,-1,sizeof(s));
			if(iddfs(0,d,b/a+1,a,b)){
				break;
			}
		}
		if(d > 100){					//No solution, I photographed 400 sets of data without a solution....
			printf("No solution.\n");
		}
		else{
			printf("%d/%d = ",a,b);
			for(int i = 0;i < d;i++){
				printf("1/%lld+",s[i]);
			}
			printf("1/%lld.\n",s[d]);
		}
	}
	return 0;
}

Iterating to deepen the second question of introduction -- chivalry

The main idea is to give you a 5 * 5 chessboard to ask if you can reach the given state within 15 steps at most. What is the minimum number of steps if it can be reached, and if it can't reach output-1. It is obvious to deepen the search problem by iteration, and make a little expected estimation with the estimation function. If you don't control the depth directly, it will definitely time out. After all, dfs is so stupid. How can he know when to stop and turn? So we use iterative deepening to control it, and the result is the best and the fastest. The problem can be found in VJ.

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int goal[5][5] = {{1,1,1,1,1},{0,1,1,1,1},
	{0,0,2,1,1},{0,0,0,0,1},{0,0,0,0,0}};
int map[5][5];
int dx[] = {2,2,-2,-2,1,1,-1,-1};
int dy[] = {1,-1,1,-1,2,-2,2,-2};
int h()				//Count the number of pieces different from the expected board
{
	int cnt = 0;
	for(int i = 0;i < 5;i++){
		for(int j = 0;j < 5;j++){
			if(map[i][j] != goal[i][j]){
				cnt++;
			}
		}
	}
	return cnt;
}
bool iddfs(int d,int maxd,int x,int y)
{
	if(h() == 0){				//If the final state is reached directly, return directly
		return true;
	}
	if(h() + d - 1 > maxd){		//Estimate
		return false;		//The number of current searches and the number of valuations and whether the answer can be reached before the maximum depth is reached
	}
	for(int i = 0;i < 8;i++){
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(nx < 0 || nx > 4 || ny < 0 || ny > 4){
			continue;
		}
		swap(map[x][y],map[nx][ny]);
		if(iddfs(d+1,maxd,nx,ny)){
			return true;
		}
		swap(map[x][y],map[nx][ny]);
	} 
	return false;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		int sx,sy,d;
		for(int i = 0;i < 5;i++){
			char s[10];
			scanf("%s",s);
			for(int j = 0;j < 5;j++){
				if(s[j] == '1' || s[j] == '0'){
					map[i][j] = s[j] - '0';
				}
				if(s[j] == '*'){
					map[i][j] = 2;
					sx = i;sy = j;
				}
			}
		}
		for(d = 1;d <= 15;d++){
			if(iddfs(0,d,sx,sy)){
				break;
			}
		}
		if(d > 15){
			printf("-1\n");
		}
		else{
			printf("%d\n",d);
		}
	}
	return 0;
}

The third problem of deepening the introduction of iteration

POJ3134
That is, to give a number N and ask how to calculate it from x^1 to x^n as soon as possible. You can use the intermediate calculation result to perform multiplication and division, but in fact, you can add and subtract the index above. So the question is reduced to 1 ------ how to get n quickly by adding or subtracting the answer obtained by the intermediate operation. And the output of the minimum number of operations, it is clear that no matter how there are solutions, but the size of the solution, the maximum number has no upper limit, but the minimum number has a lower limit. The deeper the thought depth is, the smaller the iteration depth is.

Optimistic estimation: the difference assumption of maxd-d is m, which means that m times can be expanded. Even if M times are calculated by doubling the current value, the maximum is to make the current number x double by 2^m. if it is smaller than n, then it is unnecessary to calculate it. Under this depth, X is not the answer.

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
int n,s[1005];
bool iddfs(int d,int maxd,int x)
{
	if(d > maxd || (x*(1<<(maxd-d)) < n)){		//Beyond maximum depth and optimistic estimates
		return false;		
	}
	if(x == n){						//Expand to node end search
		return true;
	}
	s[d] = x;
	for(int i = 0;i <= d;i++){			//Expand all situations
		if(iddfs(d+1,maxd,x+s[i])){		//All addition cases
			return true;
		}
		if(iddfs(d+1,maxd,fabs(x-s[i]))){
			return true;	//For all subtraction cases, remember to add the absolute value and it is not allowed that the index is negative
		}
	}
	return false;			//No answers
}
int main()
{
	while(~scanf("%d",&n) && n){
		int i;
		for(i = 0; true ;i++){
			memset(s,0,sizeof(s));
			if(iddfs(0,i,1)){
				break;
			}
		}
		printf("%d\n",i);
	}
	return 0;
}

Iterate to deepen the fourth question of getting started
Title portal HDU1667
The main idea of the question is that there are eight operations of ABCDEFGH, and only one operation can be performed at a time. Ask the minimum number of steps to make the eight blocks in the middle be one or two or three. Iteration deepening search idea + pruning skill

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int s[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[] = {6,7,8,11,12,15,16,17};			//Coordinates of 8 positions in the center
int ans[] = {5,4,7,6,1,0,3,2,-1};				//Reverse backtracking corresponding operations
int map[25];									//Digital map
char way[105];									//Operation method
int get_h()								//Optimistic estimate
{		//Find out the number of the most 1, 2, 3 positions in the middle
	int cnt[4] = {0};
	int num = -1;
	for(int i = 0;i < 8;i++){
		cnt[map[center[i]]]++;
		num = max(num,cnt[map[center[i]]]);
	}
	return 8 - num;
}
int get_move(int k)				//move
{
	int t = map[s[k][0]];
	for(int i = 0;i < 6;i++){
		map[s[k][i]] = map[s[k][i+1]];
	}
	map[s[k][6]] = t;
}
bool iddfs(int d,int maxd,int k)
{
	if(d > maxd || get_h() + d > maxd){			//Beyond the maximum allowable depth or no solution after estimation
		return false;
	}
	if(get_h() == 0){					//Target state reached
		way[d] = '\0';
		printf("%s\n%d\n",way,map[6]);
		return true;
	}
	for(int i = 0;i < 8;i++){			//Eight situation expansion
		if(ans[i] != k){				//Current search and last search are not mutually inverse, small optimization~
			way[d] = 'A' + i;
			get_move(i);				//Forward migration
			if(iddfs(d+1,maxd,i)){
				return true;
			}
			get_move(ans[i]);			//Backward shift
		}
	}
	return false;
}
int main()
{
	int n;
	while(~scanf("%d",&n) && n){
		map[0] = n;
		for(int i = 1;i < 24;i++){
			scanf("%d",&map[i]);
		}
		if(get_h() == 0){				//The given state goes directly to the target state
			printf("No moves needed\n%d\n",map[6]);
			continue;
		}
		for(int i = 1; true ;i++){
			if(iddfs(0,i,8)){
				break;
			}
		} 
	}
	return 0;
}
Published 7 original articles, won praise 2, visited 300
Private letter follow

Posted on Mon, 16 Mar 2020 06:20:47 -0400 by tallberg