蓝桥杯-跳跃(DFS+DP)

题目描述

小蓝在一个 �n 行 �m 列的方格图中玩一个游戏。

开始时,小蓝站在方格图的左上角,即第 11 行第 11 列。

小蓝可以在方格图上走动,走动时,如果当前在第 �r 行第 �c 列,他不能走到行号比 �r 小的行,也不能走到列号比 �c 小的列。同时,他一步走的直线距离不超过 33。

例如,如果当前小蓝在第 33 行第 55 列,他下一步可以走到第 33 行第 66 列、第 33 行第 77 列、第 33 行第 88 列、第 44 行第 55 列、第 44 行第 66 列、第 44 行第 77 列、第 55 行第 55 列、第 55 行第 66 列、第 66 行第 55 列之一。

小蓝最终要走到第 �n 行第 �m 列。

在图中,有的位置有奖励,走上去即可获得,有的位置有惩罚,走上去就要接受惩罚。奖励和惩罚最终抽象成一个权值,奖励为正,惩罚为负。

小蓝希望,从第 11 行第 11 列走到第 �n 行第 �m 列后,总的权值和最大。请问最大是多少?

方法一:DFS搜索

搜索出顶点到底点的所有路径,并求出所经过路径的最大权值和

import java.util.*;
public class P1 {
    static Scanner scanner = new Scanner(System.in);
    static int n= scanner.nextInt();
    static int m= scanner.nextInt();
    static int []dx={0,0,0,1,2,3,1,2,1};
    static int [][]arr=new int[n][m];
    static int []dy={1,2,3,0,0,0,1,1,2};
    static boolean[][]mark=new boolean[n][m];
    static int max_length = Integer.MIN_VALUE;
    public static void main(String[] args) {
        for (int i = 0; i < n; i++) {
            for (int j =0; j < m ; j++) {
                arr[i][j]= scanner.nextInt();
            }
        }

        dfs(0,0,arr[0][0]);
        System.out.println(max_length);

    }
    public static void  dfs(int x,int y,int length){
        if (x==n-1&&y==m-1){
            max_length= Math.max(max_length,length);
        }
        mark[x][y]=true;
        for (int i = 0; i < dx.length; i++) {
            int nx=x+dx[i];
            int ny=y+dy[i];
            if ( nx < n && ny < m){
                if ( mark[nx][ny] == false ) dfs(nx,ny,length+arr[nx][ny]);
            }
            mark[x][y]=false;
        }
    }
}

方法二:DP动态规划

定义dp[i][j]为前面的点到该点所走过的路径的最大权值和

import java.util.*;

public class P2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n=scanner.nextInt();
        int m=scanner.nextInt();
        int []dx={0,0,0,-1,-2,-3,-1,-2,-1};
        int []dy={-1,-2,-3,0,0,0,-1,-1,-2};

        int[][] map = new int[n+1][m+1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                map[i][j]= scanner.nextInt();
            }
        }

        int [][]dp=new int[n+1][m+1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                int max_value=-100;

                for (int k = 0; k < dx.length; k++) {
                    if(i+dx[k]>0&&j+dy[k]>0) max_value=Math.max(max_value,dp[i+dx[k]][j+dy[k]]);
                }
                if(i==1&&j==1){
                    dp[1][1]=map[1][1];
                }
                else dp[i][j]=max_value+map[i][j];
            }
        }
        System.out.println(dp[n][m]);
    }
}
<think>嗯,用户想要了解蓝桥杯竞赛中关于“传送阵”问题的C语言解法和实现思路。首先,我需要回想一下蓝桥杯历年的题目,是否有类似的“传送阵”问题。可能这个问题涉及到图论中的最短路径算法,比如BFS或者DFS,或者是动态规划,因为传送阵通常意味着跳跃或快速移动,可能需要计算最优路径。 用户提到的其他引用内容中有使用全排列和DFS的例子,比如算式900和红与黑的DFS解法。这说明在蓝桥杯竞赛中,DFS和暴力搜索是常见的解题方法。因此,传送阵问题可能也需要类似的搜索策略,尤其是当涉及到状态转移或多步骤决策时。 接下来,我需要确定传送阵问题的具体描述。假设传送阵允许在特定点之间瞬间移动,这可能类似于图中的边,节点代表位置,传送阵代表边。因此,求从起点到终点的最短路径可能需要使用BFS,因为BFS适合无权图中的最短路径问题。 可能的实现步骤包括: 1. 建立图的表示,比如邻接表或矩阵,记录每个位置可传送到的点。 2. 使用BFS队列来处理当前节点和步数。 3. 维护一个访问数组,避免重复访问。 4. 处理传送阵的特殊情况,比如使用传送阵后到达的位置是否需要额外处理。 另外,如果传送阵有使用次数限制或其他条件,可能需要使用优先队列(Dijkstra算法)来处理带权的情况。但根据蓝桥杯题目的难度,可能更偏向基础BFS。 参考用户提供的引用[2]中的DFS解法,红与黑问题中处理了边界条件和访问标记,类似地,在传送阵问题中也需要处理越界和访问状态。可能的陷阱包括传送后的位置是否合法,以及如何记录传送后的步数。 因此,总结可能的解题思路为:将传送阵视为图中的边,使用BFS遍历所有可能的移动方式,每次处理当前位置的普通移动和传送移动,直到找到目标位置。 最后,生成相关问题需要考虑用户可能进一步想了解的内容,比如如何优化BFS,如何处理动态传送阵,或者与其他算法结合的变体问题。</think>### 蓝桥杯“传送阵”问题C语言实现思路 #### 问题分析 传送阵问题通常涉及图论中的路径搜索,需要处理节点之间的跳跃或传送关系。核心思路是通过**广度优先搜索(BFS)**或**动态规划(DP)**解决最短路径问题。以下是具体实现步骤: #### 算法设计 1. **建模为图结构** 将传送阵的起点和终点视为图中的边。若题目中每个节点有多个传送选项,可用邻接表存储传送关系,例如: ```c #define MAX_N 1000 int graph[MAX_N][MAX_N]; // 邻接矩阵表示传送关系 ``` 2. **BFS核心逻辑** - 初始化队列,记录当前位置和已走步数。 - 每次扩展时,既考虑普通移动(如上下左右),也检查当前节点是否有传送阵可用。 - 使用访问标记数组避免重复计算: ```c int visited[MAX_N]; // 标记节点是否被访问过 ``` 3. **关键代码片段** ```c #include <stdio.h> #include <queue> using namespace std; struct Node { int pos; // 当前位置 int step; // 已用步数 }; void bfs(int start, int target) { queue<Node> q; q.push({start, 0}); visited[start] = 1; while (!q.empty()) { Node curr = q.front(); q.pop(); if (curr.pos == target) { printf("最短步数: %d\n", curr.step); return; } // 处理普通移动(如相邻节点) for (int next : adjacent[curr.pos]) { if (!visited[next]) { visited[next] = 1; q.push({next, curr.step + 1}); } } // 处理传送阵 for (int teleport : graph[curr.pos]) { if (!visited[teleport]) { visited[teleport] = 1; q.push({teleport, curr.step + 1}); } } } printf("无法到达目标位置\n"); } ``` #### 复杂度优化 - **剪枝策略**:若某个节点已被更优路径访问过,则跳过(例如步数更多的情况)。 - **双向BFS**:从起点和终点同时搜索,减少时间复杂度[^1]。 #### 典型应用场景 - 网格地图中的最短路径(如迷宫+传送门)。 - 多状态转移问题(如带传送次数限制的变体)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值