洛谷P1004 方格取数(DP)

本文介绍了一种基于四维动态规划解决特定问题的方法,重点在于如何通过递推更新状态,实现对同一位置多次访问并确保计数准确无误。文章详细展示了状态转移方程,并附带完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意分析

和P1006 差不多。
区别就是如果取走了数字,要归0,而且可以走相同的格子。
状态的定义和传纸条是一样的 。

直接 n4 n 4 的循环,然后就OK了。
注意如果是转移到同一个地方,那么这一个方格子的值只能加一次。

代码总览

#include<bits/stdc++.h>
using namespace std;
const int nmax = 60;
int mp[nmax][nmax];
int dp[nmax][nmax][nmax][nmax];
int n,m;
int getdp(){
    for(int i = 1;i<=n;++i){
        for(int j = 1;j<=n;++j){
            for(int k = 1;k<=n;++k){
                for(int l = 1;l<=n;++l){
                    dp[i][j][k][l] = max(dp[i][j][k][l],dp[i-1][j][k-1][l]);
                    dp[i][j][k][l] = max(dp[i][j][k][l],dp[i-1][j][k][l-1]);
                    dp[i][j][k][l] = max(dp[i][j][k][l],dp[i][j-1][k-1][l]);
                    dp[i][j][k][l] = max(dp[i][j][k][l],dp[i][j-1][k][l-1]);
                    dp[i][j][k][l] += (i == k && j == l)?mp[i][j]:(mp[i][j] + mp[k][l]);
                }
            }
        }
    }
    return dp[n][n][n][n];
}
int main(){
    scanf("%d",&n);
    int a,b,c;
    while(scanf("%d %d %d",&a,&b,&c)){
        if(a == 0 && b == 0 && c == 0) break;
        mp[a][b] = c;
    }
    printf("%d\n",getdp());
    return 0;
}
### 关于洛谷 P2813 的 Java 实现解决方案 对于洛谷 P2813 题目,虽然未提供具体题目描述,但从常见的解题模式来看,该类问题通常涉及图论中的最短路径计算或动态规划优化。以下是基于常见场景的一种可能实现方式。 #### 使用 Dijkstra 算法求解最短路径 如果问题是关于在一个加权图中找到从起点到终点的最短路径,则可以采用经典的 **Dijkstra 算法**来解决问题[^1]。下面是一个完整的 Java 实现: ```java import java.util.*; public class Main { static final int INF = Integer.MAX_VALUE; public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 输入节点量和边的量 int n = sc.nextInt(); // 节点 int m = sc.nextInt(); // 边 List<List<Edge>> graph = new ArrayList<>(); for (int i = 0; i <= n; i++) { graph.add(new ArrayList<>()); } // 构建邻接表表示的图 for (int i = 0; i < m; i++) { int u = sc.nextInt(); int v = sc.nextInt(); int w = sc.nextInt(); graph.get(u).add(new Edge(v, w)); } // 运行 Dijkstra 算法 int startNode = 1; int[] dist = dijkstra(graph, startNode); // 输出结果 System.out.println(Arrays.toString(dist)); } private static int[] dijkstra(List<List<Edge>> graph, int start) { PriorityQueue<Node> pq = new PriorityQueue<>(Comparator.comparingInt(o -> o.distance)); int[] distances = new int[graph.size()]; Arrays.fill(distances, INF); distances[start] = 0; pq.offer(new Node(start, 0)); while (!pq.isEmpty()) { Node current = pq.poll(); if (current.distance > distances[current.vertex]) continue; for (Edge edge : graph.get(current.vertex)) { int neighbor = edge.to; int weight = edge.weight; if (distances[current.vertex] + weight < distances[neighbor]) { distances[neighbor] = distances[current.vertex] + weight; pq.offer(new Node(neighbor, distances[neighbor])); } } } return distances; } static class Edge { int to; int weight; public Edge(int to, int weight) { this.to = to; this.weight = weight; } } static class Node { int vertex; int distance; public Node(int vertex, int distance) { this.vertex = vertex; this.distance = distance; } } } ``` 上述代码实现了带权重的无向图中最短路径的查找功能。它利用优先队列加速了传统 BFS 的过程,从而使得复杂度降低至 \(O((V+E)\log V)\)[^1]。 --- #### 动态规划思路(适用于网格型问题) 如果是类似于引用[4]提到的方格迷宫问题,则可以通过二维 DP 表达状态转移关系。假设目标是从左上角走到右下角,每一步只能向下或者向右移动,那么可以用如下公式定义状态转移方程: \[ dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + grid[i][j] \] 其中 `grid` 是存储每个位置代价的矩阵,而 `dp` 组记录到达某一点所需的最小总成本。 下面是对应的伪代码转换成实际程序的例子: ```java import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] nm = br.readLine().split(" "); int n = Integer.parseInt(nm[0]); int m = Integer.parseInt(nm[1]); int[][] grid = new int[n][m]; for (int i = 0; i < n; ++i) { String line = br.readLine(); for (int j = 0; j < m; ++j) { grid[i][j] = Character.getNumericValue(line.charAt(j)); } } int[][] dp = new int[n][m]; // 初始化边界条件 dp[0][0] = grid[0][0]; for (int i = 1; i < n; ++i) dp[i][0] = dp[i - 1][0] + grid[i][0]; for (int j = 1; j < m; ++j) dp[0][j] = dp[0][j - 1] + grid[0][j]; // 填充剩余部分 for (int i = 1; i < n; ++i) { for (int j = 1; j < m; ++j) { dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]; } } System.out.println(dp[n - 1][m - 1]); // 输出最终答案 } } ``` 这种做法的时间复杂度为 \(O(NM)\),非常适合大规模输入的据范围[^4]。 --- #### 注意事项 在提交之前,请务必注意以下几点: - 如果存在多组测试样例,需在外层循环读所有据并分别处理。 - 对于大整运算的情况,考虑使用 BigInteger 类替代基本类型变量[^3]。 - 提交时应关闭标准输入流以防止超时错误发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值