今天学习背包DP(Knapsack DP)
是USACO Guide的DP章节中第三点
What is grid DP? -Summary
DP problems often involve a 2D grid where paths are analyzed. Movement is restricted to one direction on the x-axis and y-axis, typically starting from one corner and ending at another. The goal may be to count paths or find max/min values. Sub-problems are sub-rectangles of the grid. For instance, to count paths from 1,1 to N,M moving positively, we define dp[x][y] as the number of paths to x,y. The recurrence relation is dp[x][y] = dp[x-1][y] + dp[x][y-1], with dp[1][1] = 1. Understanding cell appending aids in forming the correct recurrence.
简单来说,DP 问题通常涉及分析路径的时候使用2D的数组。移动仅限于 x 轴和 y 轴上的一个方向,通常从一个角开始并在另一个角结束。目标可能是对路 径进行计数或查找最大/最小值。子问题是网格的子矩形。例如,为了计算从 1,1 到 N,M 正向移动的路径,我们将 dp[x][y] 定义为到 x,y 的路径数。递推关系为 dp[x][y] = dp[x-1][y] + dp[x][y-1],其中 dp[1][1] = 1。理解单元格附加有助于形成正确的规律。
代表题目Grip Paths
Consider an n×n grid whose squares may have traps. It is not allowed to move to a square with a trap.
Your task is to calculate the number of paths from the upper-left square to the lower-right square. You can only move right or down.
Input
The first input line has an integer n: the size of the grid.
After this, there are nnn lines that describe the grid. Each line has n characters: .
denotes an empty cell, and *
denotes a trap.
Output
Print the number of paths modulo 10^9+7
Constraints
- 1≤n≤1000
Example
Input:
4 .... .*.. ...* *...
Output:
3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool ok[1000][1000];
ll dp[1000][1000];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
for (int j = 0; j < n; j++) {
if (s[j] == '.') ok[i][j] = true;
else ok[i][j] = false;
}
}
dp[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!ok[i][j]) dp[i][j] = 0;
else {
if (i > 0) dp[i][j] += dp[i - 1][j];
if (j > 0) dp[i][j] += dp[i][j - 1];
dp[i][j] %= 1000000007;
}
}
}
cout << dp[n - 1][n - 1] << "\n";
return 0;
}
思路
In this problem, we are directly given a 2D grid of cells, and we have to count the number of paths from corner to corner that can only go down (positive yyy direction) and to the right (positive xxx direction), with a special catch. The path can't use a cell marked with an asterisk.
We come close to being able to use our original recurrence, but we have to modify it. Basically, if a cell (x,y)(x, y)(x,y) is normal, we can use the recurrence normally. But, if cell (x,y)(x, y)(x,y) has an asterisk, the dp-value is 000, because no path can end on a trap.
在这个问题中直接给我们了一个2D元网格,我们必须用一个特殊的判断方法计算从一个角落到另一个角落只能向下的路径数量(正 y方向)和向右(正 x 方向)。这路径不能使用标有星号的单元格。
我们已经接近能够使用原来的递归方式了,但是我们必须修改它。简单来速回,如果一个单元格 (x, y) 是正常的,我们可以使用递归通常情况下。但是,如果单元格 (x, y) 有星号,则 dp 值为 0,因为没有路径可能以陷阱(*)结束。