PTA 7-1 666 作者 DS课程组 单位 临沂大学

小明有一张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;
}

总结:第一次亲眼见到java和c++的速度差距。以后算法能用c++就不要用Java吧,尤其对于我这种菜鸡🙂😄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值