【动态规划】DFS

本文探讨了一种通过动态规划解决滑雪场最长滑雪路径的问题,使用深度优先搜索(DFS)算法来寻找从任意点出发的最长连续下降路径。在给定的地形高度网格中,算法检查所有可能的方向,以确定最长的连续下降路线。

动态规划DGA

????????

点击打开题目并提交

凯旋喜欢滑雪板。这并不奇怪,因为单板滑雪真的很棒。不好的是,为了获得速度,该区域必须向下滑动。另一个缺点是,当你到达山脚时,你必须再次走上或等待滑雪缆车。
凯旋想知道一个地区最长跑的时间。该区域由数字网格给出,定义了这些点的高度。看看这个例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
当且仅当高度降低时,可以从一个点向下滑动到连接的另一个点。如果它在左侧,右侧,上方或下方,则一个点连接到另一个点。在样本地图中,可能的幻灯片是24-17-16-1(从24开始,在1结束)。当然如果你去25-24-23-。 。 。 -3-2-1,它会
是一个更长的运行。事实上,这是最长的。
输入
第一行包含测试用例N的数量。每个测试用例以包含该行的行开头
name(它是单个字符串),行数R和列数C.之后是R
每行都有C编号,定义高度。 R和C不会大于100,N不大于
15和高度始终在0到100的范围内。
产量
对于每个测试用例,打印一行包含区域名称,冒号,空格和长度
最长的跑步者可以在该区域滑下来。
 

样例输入
2
Feldberg 10 5
56 14 51 58 88
26 94 24 39 41
24 16 8 51 51
76 72 77 43 10
38 50 59 84 81
5 23 37 71 77
96 10 93 53 82
94 15 96 69 9
74 0 62 38 96
37 54 55 82 38
Spiral 5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

样例输出

Feldberg: 7
Spiral: 25 

dfs其实挺好玩,详细题解都写在注释里了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dx[]={0,1,0,-1},
	dy[]={1,0,-1,0};
int map[102][102];
int vis[102][102];//用来记录 
int dfs(int x,int y)
{
	if(vis[x][y])//如果这个点以前找过,就不用找了,直接返回 
	return vis[x][y];
	int a,b;
	int anslen=0,k=0;
	for(int i=0;i<4;i++)//向四个方向移动 
	{
		a=x+dx[i];
		b=y+dy[i];
		if(map[a][b]<map[x][y])
		k=dfs(a,b);
		if(k>anslen)
		anslen=k;
	}
	anslen++; //找出这个点所有的连接的最长的路段 
	return	anslen;
}
int main()
{
	int t,n,k,len;
	string name;
	while(cin>>t)
	{
		while(t--)
		{
			len=0;
			memset(vis,0,sizeof(vis));//初始化避免上次数据的 污染 
			memset(map,0x7f,sizeof(map));	//0x7f为int类型的最大值 
			cin>>name>>n>>k;
			for(int i=1;i<=n;i++)
			{
				map[i][0]=0x7f;//边界不能访问,所以设置为无穷大
				for(int j=1;j<=k;j++)
				{
					map[0][j]=0x7f;//边界不能访问,所以设置为无穷大
					cin>>map[i][j];
				}
			}
			for(int i=1;i<=n;i++)
			for(int j=1;j<=k;j++)
			len=max(len,dfs(i,j));
			cout<<name<<": "<<len<<endl;
		}
	}
	return 0;
}

 

### 使用 DFS 实现动态规划的解决方案 #### 动态规划与深度优先搜索的关系 动态规划的核心在于“聪明的穷举”,而这种穷举可以通过深度优先搜索 (DFS) 来实现。尽管并非所有的 DFS 题目都能转化为动态规划问题,但大多数动态规划问题可以从 DFS 的角度出发逐步优化至动态规划方案[^1]。 #### 记忆化搜索的作用 在从 DFS动态规划过渡的过程中,记忆化搜索起到了桥梁作用。通过记录子问题的结果,可以有效减少重复计算,从而提高效率。这种方法本质上就是自顶向下的动态规划[^3]。 --- ### 示例:0/1 背包问题 #### 问题描述 给定一组物品,每种物品都有自己的重量和价值,在限定总重量的前提下,求解能获得的最大价值。 #### 基于 DFS 的初始解法 以下是基于 DFS 的简单递归实现: ```python def dfs_knapsack(index, current_weight, weights, values, max_weight): if index >= len(weights): # 边界条件 return 0 # 不选当前物品的情况 res = dfs_knapsack(index + 1, current_weight, weights, values, max_weight) # 如果可以选择当前物品,则尝试选择 if current_weight + weights[index] <= max_weight: res = max(res, values[index] + dfs_knapsack( index + 1, current_weight + weights[index], weights, values, max_weight)) return res ``` 此方法虽然直观,但在复杂度较高的情况下容易超时[^2]。 --- #### 添加记忆化的改进版本 为了提升性能,可以在上述基础上引入记忆化存储中间状态的结果: ```python from functools import lru_cache def memoized_dfs_knapsack(weights, values, max_weight): n = len(weights) @lru_cache(None) def dfs(index, current_weight): if index == n or current_weight > max_weight: # 终止条件 return 0 # 不选当前物品 result = dfs(index + 1, current_weight) # 尝试选择当前物品 if current_weight + weights[index] <= max_weight: result = max(result, values[index] + dfs(index + 1, current_weight + weights[index])) return result return dfs(0, 0) ``` 这种方式显著减少了冗余计算,使得时间复杂度接近动态规划的时间复杂度。 --- #### 完全转换为动态规划 最终,我们可以将上述逻辑进一步优化为标准的动态规划形式: ```python def knapsack_dp(weights, values, max_weight): n = len(weights) dp = [[0] * (max_weight + 1) for _ in range(n + 1)] for i in range(1, n + 1): for w in range(max_weight + 1): if weights[i - 1] <= w: dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]) else: dp[i][w] = dp[i - 1][w] return dp[n][max_weight] ``` 以上代码展示了如何从 DFS 和记忆化搜索逐渐演变为经典的动态规划表结构。 --- ### 示例:N 皇后问题 #### 问题描述 在一个 \( n \times n \) 的棋盘上放置 \( n \) 个皇后,使它们互不攻击。返回所有可能的摆放方式。 #### 基于 DFS 的解法 利用 DFS 枚举每一行的所有可能性,并通过剪枝排除非法情况: ```python def solve_n_queens(n): board = [["."] * n for _ in range(n)] solutions = [] cols = set() diag1 = set() # 主对角线 diag2 = set() # 副对角线 def backtrack(row): if row == n: solutions.append(["".join(row) for row in board]) return for col in range(n): if col in cols or (row - col) in diag1 or (row + col) in diag2: continue # 更新标记集合并放置皇后 cols.add(col) diag1.add(row - col) diag2.add(row + col) board[row][col] = "Q" # 进入下一层决策树 backtrack(row + 1) # 撤销操作 cols.remove(col) diag1.remove(row - col) diag2.remove(row + col) board[row][col] = "." backtrack(0) return solutions ``` 该方法通过回溯实现了枚举过程,同时借助辅助数据结构完成冲突检测[^5]。 --- ### 总结 无论是背包问题还是 N 皇后问题,都表明了 DFS 是一种通用性强、易于理解的方法,但它通常伴随着高时间开销。通过加入记忆化机制或彻底重构为动态规划表格,能够大幅降低运行成本,同时保留解决问题的能力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值