小明有一张m*n的好习惯记录卡,记录每一天的好习惯目标达成度(数字0-9表示)。某天目标完成达成,就在当天的格子里写上数字6,目标没有完全达成就写上一个小于6的数字(0-5),目标超额完成就写上一个大于6的数字(7-9)。记录卡上如果能找到一条长度为3的路径并且路径上的三个数字都大于等于6(这里的路径是指从某个格子出发,可以向左、右、上、下格子移动,并且不能重复经过一个格子),则小明就能得到一个“666”奖励。
请你帮小明统计下他总共能得到多少“666”奖励。
输入格式:
输入第一行给出两个正整数m,n(1=<m,n<=100),随后是m行,每行包含n个0-9之间的数字。
输出格式:
先输出m行,每行包括n个整数,代表从当前格子出发得到的“666”奖励个数,中间用空格分割,最后一个数字后面不带空格。然后再在下一行输出得到的“666”奖励总数。
输入样例:
3 3
6 6 7
3 8 3
7 9 5
输出样例:
2 1 2
0 3 0
1 1 0
10
快期末考试了,把为数不多自己写的题记下(主要是没在网上找到答案😭)
DFS深搜,剪枝,记忆化(不用dp最后一个点会超时)
重点!!!同样的思路用Java写,可最后一个点永远是超时!!!
下面是Java代码:
import java.util.*;
public class Homework01 {
static final int[] dx = {-1, 1, 0, 0};
static final int[] dy = {0, 0, -1, 1};
static int[][] result = new int[101][101];
static int[][] grid = new int[101][101];
static int totalCount = 0;
static int cnt = 0;
static Map<String, Integer> dp = new HashMap<>(); // 使用 Map 替代 四维 int 数组,避免超内存
static int xx = 0;
static int yy = 0;
static boolean isValid(int x, int y, int m, int n) {
return x >= 0 && x < m && y >= 0 && y < n;
}
// 生成 Map 键
static String getKey(int x, int y, int xx, int yy) {
return x + "," + y + "," + xx + "," + yy;
}
static void dfs(int x, int y, int m, int n, int[][] grid, boolean[][] visited, int length) {
if (length == 3) {
cnt++;
totalCount++;
String key = getKey(x, y, xx, yy);
dp.put(key, dp.getOrDefault(key, 0) + 1);
return;
}
visited[x][y] = true;
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
xx = newX;
yy = newY;
if (isValid(newX, newY, m, n) && !visited[newX][newY] && grid[newX][newY] >= 6) {
String key = getKey(x, y, newX, newY);
if (!dp.containsKey(key)) {
dfs(newX, newY, m, n, grid, visited, length + 1);
} else {
cnt += dp.get(key);
}
}
}
// 恢复现场
visited[x][y] = false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = sc.nextInt();
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] >= 6) { // 只有当前格子的值大于等于6时,才开始计算
boolean[][] visited = new boolean[m][n];
xx = i;
yy = j;
dfs(i, j, m, n, grid, visited, 1);
result[i][j] = cnt;
cnt = 0;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n - 1; j++) {
System.out.print(result[i][j] + " ");
}
System.out.println(result[i][n - 1]);
}
System.out.println(totalCount);
}
}
于是我原封不动把思路照搬换成c++,过了!!!
下面是c++代码:
#include <bits/stdc++.h>
using namespace std;
const int dx[4] = { -1, 1, 0, 0 };
const int dy[4] = { 0, 0, -1, 1 };
vector<vector<int>> result(101, vector<int>(101, 0));
vector<vector<int>> grid(101, vector<int>(101, 0));
int totalCount = 0;
int cnt = 0;
unordered_map<string, int> dp; // 使用 Map 替代 四维 int 数组,避免超内存
int xx = 0;
int yy = 0;
bool isValid(int x, int y, int m, int n) {
return x >= 0 && x < m && y >= 0 && y < n;
}
// 生成 Map 键
string getKey(int x, int y, int xx, int yy) {
return to_string(x) + "," + to_string(y) + "," + to_string(xx) + "," + to_string(yy);
}
void dfs(int x, int y, int m, int n, vector<vector<int>>& grid, vector<vector<bool>>& visited, int length) {
if (length == 3) {
cnt++;
totalCount++;
string key = getKey(x, y, xx, yy);
dp[key]++;
return;
}
visited[x][y] = true;
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
xx = newX;
yy = newY;
if (isValid(newX, newY, m, n) && !visited[newX][newY] && grid[newX][newY] >= 6) {
string key = getKey(x, y, newX, newY);
if (dp.find(key) == dp.end()) {
dfs(newX, newY, m, n, grid, visited, length + 1);
}
else {
cnt += dp[key];
}
}
}
// 恢复现场
visited[x][y] = false;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int m, n;
cin >> m >> n;
grid.resize(m, vector<int>(n));
result.resize(m, vector<int>(n, 0));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> grid[i][j];
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] >= 6) { // 只有当前格子的值大于等于6时,才开始计算
vector<vector<bool>> visited(m, vector<bool>(n, false));
xx = i;
yy = j;
dfs(i, j, m, n, grid, visited, 1);
result[i][j] = cnt;
cnt = 0;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n - 1; j++) {
cout << result[i][j] << " ";
}
cout << result[i][n - 1] << endl;
}
cout << totalCount << endl;
return 0;
}