蓝桥杯-跳跃(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]);
    }
}
### 关于蓝桥杯 C++ 编程题目及其解法 #### 题目背景与分析 蓝桥杯竞赛中的编程问题通常涉及算法设计、数据结构应用以及优化技巧。以下是一些常见的题型解析: 1. **树形动态规划 (Tree DP)** 给定一棵树,要求通过某种方式计算节点的属性值。例如,在引用[1]中提到的一个经典问题是关于子树的最大贡献值计算[^1]。此问题可以通过深度优先搜索(DFS)实现,并利用数组 `f` 来存储每个节点的结果。 2. **多重计数校正** 当涉及到多个集合之间的交集运算时,可能会遇到重复计数的情况。引用[2]描述了一个典型的例子:当某些条件成立时,需要调整最终结果以消除多余或不足的部分[^2]。这种类型的题目常见于组合数学领域。 3. **简单输入输出操作** 对于初学者来说,掌握基本的输入输出方法非常重要。比如引用[3]展示了一个简单的加法程序,它接收两个整数作为输入并打印它们的和[^3]。虽然看似基础,但对于熟悉语法很有帮助。 4. **经济模型模拟** 参考引用[4]提到了一个有关资源分配的问题——如何最小化花费来满足特定需求?这类问题可能需要用到贪心策略或者线性规划等高级技术[^4]。 #### 示例代码片段 以下是针对上述几种情况所提供的部分解决方案示例: ```cpp // 树形DP模板 #include <bits/stdc++.h> using namespace std; long long n, x, f[100005]; vector<long long> v[100005]; void dfs(long long node){ for(auto child : v[node]){ dfs(child); f[node] = max(f[node], f[child]); } f[node] += v[node].size(); } int main(){ cin >> n; for(int i=2;i<=n;i++){ cin >> x; v[x].push_back(i); } dfs(1); cout << f[1] << endl; } ``` ```cpp // 处理多重计数修正逻辑 #include <iostream> using namespace std; int A[100005], B[100005], C[100005]; long long res = 0; int main() { int N; cin >> N; for(int i=1;i<=N;i++) cin>>A[i]>>B[i]>>C[i]; // 计算初步结果 for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) for(int k=1;k<=N;k++) res += A[i]*B[j]*C[k]; // 扣除重复项 for(int i=1;i<=N;i++) { res -= A[i]*B[i]*(B[i]-1)/2 * C[i]; // Case: i == j res -= A[i]*C[i]*(C[i]-1)/2 * B[i]; // Case: k == l res -= A[i]*C[i]*B[i]; // Case: i == l && k == j res += A[i]*(A[i]-1)*(B[i]+C[i])/2; // Special case adjustment when all indices are equal. } cout<<res*(res-1)<<endl; } ``` ```python # 基础IO练习 a, b = map(int, input().split()) print(a + b) ``` #### 总结说明 以上内容涵盖了从入门到进阶的不同层次挑战项目。无论是构建复杂的递归函数还是解决实际生活场景下的预算管理难题,都能找到相应的理论依据和技术支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值