蓝桥杯DFS专题

1、排列数字

给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式
共一行,包含一个整数 n。

输出格式
按字典序输出所有排列方案,每个方案占一行。

数据范围
1≤n≤7
输入样例:

3
1
输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
————————————————
代码:

c++版

#include <iostream>
using namespace std;
const int N = 10;
int n;
int path[N];//保存数字组合
bool st[N];//检测该数字有没有用过
void dfs(int x)
{
	if (x==n)
	{
		for (int i = 0; i < n; i++)
		{
			cout << path[i];
		}
		cout << endl;
		return;
	}

	for (int i = 1; i <= n; i++)
	{
		if (!st[i])
		{
			path[x] = i;
			st[i] = true;
			dfs(x + 1);
			st[i] = false;//恢复原样
		}
	}
}
int main()
{
	cin >> n;
	dfs(0);
	return 0;
}

python版

a=[False for _ in range(10)]
N=10
path=[0]*N
n=int(input())
def dfs(u):
    if u==n:
        for i in range(3):
            print(path[i],end='')
        print()
    for i in range(1,n+1):
        if (a[i]==False):
            path[u]=i
            a[i]=True
            dfs(u+1)
            a[i]=False
dfs(0)

2、n皇后问题

输入格式
共一行,包含整数 n。

输出格式
每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。

其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。

每个方案输出完成后,输出一个空行。

注意:行末不能有多余空格。

输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…
 ————————————————

会超时

最原始的方法,每个格子都有放跟不放的选择,一个一个格子的暴搜

需要创建一个行数组,列数组,正对角线数组,反对角线数组。来检测如果要放皇后符不符合题目标准

c++版

#include <iostream>
using namespace std;
const int N = 20;
bool row[N], col[N], dg[N], udg[N];//行,列,正对角线,反对角线
char g[N][N];
int n;
void dfs(int x,int y,int s)//x是行,y是列,s是放棋子的个数
{
	if (y == n)
	{
		y = 0;
		x++;
	}
	if (x == n)
	{
		if (s == n)
		{
			for (int i = 0; i < n; i++)
			{
				for (int j = 0; j < n; j++)
				{
					cout << g[i][j];
				}
				cout << endl;
			}
			cout << endl;
		}
		return;
	}
	//不放皇后
	dfs(x, y + 1, s);
	//放皇后
	if (!row[x] && !col[y] && !dg[x + y] && !udg[y - x + n])
	{
		g[x][y] = 'Q';
		row[x] = col[y] = dg[x + y] = udg[y - x + n] = true;
		dfs(x, y + 1, s + 1);
		row[x] = col[y] = dg[x + y] = udg[y - x + n] = false;
		g[x][y] = '.';
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			g[i][j] = '.';
		}
	}
	dfs(0, 0, 0);
	return 0;
}

剪枝优化 

u代表的是每一行,所以不需要开行数组来记录

且该写法不需要每个格子都看,而是一行一行看

#include <iostream>
using namespace std;
const int N = 20;
bool col[N], dg[N], udg[N];
char g[N][N];
int n;
void dfs(int u)
{
	if (u == n)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				cout << g[i][j];
			}
			cout << endl;
		}
		cout << endl;
		return;
	}
	for (int i = 0; i < n; i++)
	{
		if (!col[i] && !dg[i+u] && !udg[i-u+n])
		{
			g[u][i] = 'Q';
			col[i] = dg[i + u] = udg[i - u + n] = true;
			dfs(u + 1);
			col[i] = dg[i + u] = udg[i - u + n] = false;
			g[u][i] = '.';
		}
	}
	
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			g[i][j] = '.';
		}
	}
	dfs(0);
	return 0;
}

python版

def dfs(u):
    if (u==n):
        for i in range(n):
            for j in range(n):
                print(g[i][j],end='')
            print()
        print()
    for i in range(n):
        if not col[i] and not dg[u+i] and not udg[i-u+n]:
            g[u][i]='Q'
            col[i]=dg[u+i]=udg[i-u+n]=True
            dfs(u+1)
            col[i]=dg[u+i]=udg[i-u+n]=False
            g[u][i]='.'

n=int(input().strip())
g=[['.' for i in range(n)] for j in range(n)]##创建该皇后棋盘
col=[False for i in range(n)]
dg=[False for i in range(2*n)]
udg=[False for i in range(2*n)]
dfs(0)

4957. 飞机降落​​​​​​​ 

有 NN 架飞机准备降落到某个只有一条跑道的机场。

其中第 ii 架飞机在 TiTi 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 DiDi 个单位时间,即它最早可以于 TiTi 时刻开始降落,最晚可以于 Ti+DiTi+Di 时刻开始降落。

降落过程需要 LiLi 个单位时间。

一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。

请你判断 NN 架飞机是否可以全部安全降落。

输入格式

输入包含多组数据。

第一行包含一个整数 TT,代表测试数据的组数。

对于每组数据,第一行包含一个整数 NN。

以下 NN 行,每行包含三个整数:TiTi,DiDi 和 LiLi。

输出格式

对于每组数据,输出 YES 或者 NO,代表是否可以全部安全降落。

数据范围

对于 30%30% 的数据,N≤2N≤2。
对于 100%100% 的数据,1≤T≤101≤T≤10,1≤N≤101≤N≤10,0≤Ti,Di,Li≤1050≤Ti,Di,Li≤105。

输入样例:

2
3
0 100 10
10 10 10
0 2 20
3
0 10 20
10 10 20
20 10 20

输出样例:

YES
NO

样例解释

对于第一组数据,可以安排第 33 架飞机于 00 时刻开始降落,2020 时刻完成降落。安排第 22 架飞机于 2020 时刻开始降落,3030 时刻完成降落。安排第 11 架飞机于 3030 时刻开始降落,4040 时刻完成降落。

对于第二组数据,无论如何安排,都会有飞机不能及时降落。


题解:

用dfs一个一个可能枚举,假设我们按飞机顺序来枚举,第一架飞机降落到地面的时间总共就是到机场上空的时间加上降落的时间,如果我们要看后面一架飞机能不能降落,就需要第二架飞机到机场上空的时间加上可以盘旋的时间(燃油)>=第一架所消耗的时间。


#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int T,n;
const int N = 10;

struct plane
{
    int t,d,l;
}q[N];
bool st[N];

bool dfs(int u,int last)//不能超过last,不然飞机降落不了
{
    if (u==n)
    {
        return true;
    }
    for (int i=0;i<n;i++)
    {
        int t=q[i].t,d=q[i].d,l=q[i].l;
        if (!st[i] && t+d>=last)
        {
            st[i]=true;
            if (dfs(u+1,max(last,t)+l))
            {
                return true;
            }
            st[i]=false;
        }
    }
    return false;
}



int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d",&n);
        for (int i=0;i<n;i++)
        {
            int t,d,l;
            scanf("%d%d%d", &t, &d,&l);
            q[i]={t,d,l};
        }
        memset(st, 0, sizeof st);
        if (dfs(0,0))
        {
            puts("YES");
        }
        else
        {
            puts("NO");
        } 
    }
    return 0;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值