[Aftertaste "classic"] DFS basic training (N Queen, loading problem)

This article is a reedited version of "Introduction to "Deep Search Basic Training", Stepping into the Palace of C++ Algorithms (1) and  "Introduction to "Deep Search Basic Training", Stepping into the Palace of C++ Algorithms (2) written a year ago  .

I hope this will bring back memories of the old man.

Xiaohang walked into the arena, the game is about to start...

Moderator: Welcome to the competition site of Deep Search Basic Training. First of all, thanks to the teachers who have dug holes for us wholeheartedly and racked their brains to solve the problem ; then, thanks to the eccentric farmer John; finally, thanks to c++... stop talking nonsense, the competition begins!

Xiaohang looked at the first question...


[Search and Backtracking Algorithm] N Queens Problem

Xiaohang sees (title)

Time limit: 1000 ms Space limit: 262144 KB Specific limit

Title description:

Place n(n<=12) queens on an nXn chess board so that they cannot attack each other (that is, any two queens cannot be on the same row, column or diagonal). Try to figure out all the ways.

enter:

Enter a number n .(n<=12)

output:

Output the total number of all permutations.

Sample input:

4

Sample output:

2

 Xiaohang thought of (thought of thinking)

1. Legal inspection

That is, it needs to judge:

1) Are they in the same column

2) Is it on the left slash: the values ​​of (row + column) cannot be equal (absolute value)

3) Whether on the right slash: (column - row) values ​​are not equal (absolute value)

4) Why is there no need to judge each row?

Because in DFS, x already represents a row, and according to the algorithm, there is only one row, so there is no need to judge.

3. DFS search

1) End condition: current row number = total number of queens, that is, the last row has been successfully placed into the queen

2) Loop through each position in a row, if no attack event occurs, the queen can be placed in this position

3) Continue to search for the next line, that is, the parameter passed in is the current line number + 1

Xiaohang wrote (code)

#include<iostream>
using namespace std;
int a[105],b[105],c[105],n,s;//数组a为判断列是否放置皇后,b、c都是判断对角线是否放置皇后
void dg(int x)//循环行
{
	for(int i=1;i<=n;i++)//循环列
	{
		if(a[i]!=1&&b[x+i]!=1&&c[i-x+n-1]!=1)
		{
			a[i]=1;
			b[i+x]=1;
			c[i-x+n-1]=1;//上面两步及这步都是标记
			if(x==n)
			{
				s++;//当放到最后一个,方案数增加
			}
			else
			{
				dg(x+1);//进入下一行放置
			
			}	
                a[i]=0;
				b[i+x]=0;
				c[i-x+n-1]=0;//回溯
		} 
	} 
}
int main()
{
	cin>>n;
	dg(1);
	cout<<s;//输出方案数
}

Xiaohang quickly finished the first question and was ready for the next question...


[Search and Backtracking Algorithm] Loading Problem (Standard IO)

Time limit: 1000 ms Space limit: 262144 KB Specific limit

Title description:

There is a batch of n containers to be loaded on a ship with a load capacity of c, and the weight of container i is wi. Find an optimal loading scheme to fill the ship as full as possible, that is, load as heavy a container as possible on the ship when the loading volume is not limited.

enter:

The first line has 2 positive integers n and c. n is the number of containers, and c is the load capacity of the ship. There are n positive integers in the next 1 line, representing the weight of the container.

output:

Output the calculated maximum load weight

Sample input:

5 10
7 2 6 5 4

Sample output:

10

Data Range Restrictions:

n<=35,c<=1000

"Actually, this is a super simple knapsack problem , which can be solved with recursion." Xiaohang thought, " Create a temporary weight and a final weight, and search for each number (selected or not), as long as the search result is greater than the final result, Just assign the value ."

#include<iostream>
using namespace std;
int n,c,w[40],s;
void dfs(int x,int sx)//第x个物品,sx为临时重量
{
	if(x>n)
	{
		if(sx>s) s=sx;//赋值
		return;
	}
	else
	{
		if(sx+w[x]<=c)//如果装入此物品,还没超载的话……
		{
			dfs(x+1,sx+w[x]);//装入此物品,并搜索下一件物品
		}
		dfs(x+1,sx);//在不装入此物品的情况下,搜索下一件物品
	}
}
int main()
{
	cin>>n>>c;
	for(int i=1;i<=n;i++) cin>>w[i];
	dfs(1,0);
	cout<<s;//输出最终重量
}

       but. Xiaohang later found out that this seemingly simple program almost timed out. Not reconciled, he modified it:

#include<bits/stdc++.h>
using namespace std;
int n,c,w[40],s,b[40],ms=0;
void dg(int x)
{
	if(s>=c)
	{
		if(s==c)
		{
			printf("%d",s);
			exit(0);
		}
		s-=w[x-1];
		if(ms<s)
			ms=s;
		s+=w[x-1];
	}
	else if(x==n)
	{
		if(ms<s)
			ms=s;
	}
	else
	{
		s+=w[x];
		dg(x+1);
		s-=w[x];
		dg(x+1);
	}
	return;
}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
		scanf("%d",&w[i]);
	dg(0);
	printf("%d",ms);
	return 0;
} 

#include<bits/stdc++.h>
using namespace std;
int n,c,w[40],s,b[40],ms=0;
void dg(int x)
{
    if(s>=c)
    {
        if(s==c)
        {
            printf("%d",s);
            exit(0);
        }
        s-=w[x-1];
        if(ms<s)
            ms=s;
        s+=w[x-1];
    }
    else if(x==n)
    {
        if(ms<s)
            ms=s;
    }
    else
    {
        s+=w[x];
        dg(x+1);
        s-=w[x];
        dg(x+1);
    }
    return;
}
int main()
{
    scanf("%d%d",&n,&c);
    for(int i=0;i<n;i++)
        scanf("%d",&w[i]);
    dg(0);
    printf("%d",ms);
    return 0;
}  

        This shortens the running time a lot.


        After that, the next question came into view...

Guess you like

Origin blog.csdn.net/aliyonghang/article/details/132417989