935. Knight Dialer

在这里插入图片描述
又是一道很有意思的题目。
自己又没有想到图上面去:(
以后类似这种两点之间有关联的,可以联想到图上面去,把邻接表写出来就容易多了。

class Solution {
public:
    int knightDialer(int N) {
        vector<vector<int>> adj{{4, 6}, {6, 8}, {7, 9}, {4, 8}, {0, 3, 9}, {}, {0, 1, 7}, {2, 6}, {1, 3}, {2, 4}};
        
        map<pair<int, int>, int> memo;
        int cnt = 0;
        for (int i = 0; i <= 9; ++i)
            cnt = (cnt + helper(adj, memo, i, N-1)) % MOD;
        return cnt;
    }
private:
    int MOD = 1e9 + 7;
    int helper(vector<vector<int>>& adj, map<pair<int, int>, int>& memo, int pos, int steps) {
        if (steps == 0)
            return 1;
        if (pos == 5)//为了提高效率,没有这一句也是对的
            return 0;
        auto key = make_pair(pos, steps);
        if (memo.find(key) != memo.end())
            return memo[key];
        int cnt = 0;
        for (int nextPos : adj[pos])
            cnt = (cnt + helper(adj, memo, nextPos, steps-1)) % MOD;
        memo[key] = cnt;
        if (pos == 5)
            cout << pos << " " << steps << " " << cnt << endl;
        return cnt;
    }
};
//想像成一个图的题目,可以走的两个键可以看成是相邻的两个点。把邻接表写出来,然后按着邻接表来走。这是没有想出来的关键。

//然后可以意识到重叠子问题:状态是<当前位置,还剩步数>

//对于5这个特殊键:如果最后一步走到5上,返回1;如果不是最后一步走到5上,那么就应该返回0,因为走不出去了,不能把所有步数都走完

后来发现超时。可能每次都make_pair时间有点久,而且map的查询时间也不是常数。
下面换成二维数组来存储。

class Solution {
public:
    int knightDialer(int N) {
        vector<vector<int>> adj{{4, 6}, {6, 8}, {7, 9}, {4, 8}, {0, 3, 9}, {}, {0, 1, 7}, {2, 6}, {1, 3}, {2, 4}};
        
        vector<vector<int>> memo(10, vector<int>(N, -1));
        int cnt = 0;
        for (int i = 0; i <= 9; ++i)
            cnt = (cnt + helper(adj, memo, i, N-1)) % MOD;
        return cnt;
    }
private:
    int MOD = 1e9 + 7;
    int helper(vector<vector<int>>& adj, vector<vector<int>>& memo, int pos, int steps) {
        if (steps == 0)
            return 1;
        if (pos == 5)
            return 0;
        if (memo[pos][steps] != -1)
            return memo[pos][steps];
        int cnt = 0;
        for (int nextPos : adj[pos])
            cnt = (cnt + helper(adj, memo, nextPos, steps-1)) % MOD;
        memo[pos][steps] = cnt;
        return cnt;
    }
};
//想像成一个图的题目,可以走的两个键可以看成是相邻的两个点。把邻接表写出来,然后按着邻接表来走。这是没有想出来的关键。

//然后可以意识到重叠子问题:状态是<当前位置,还剩步数>

//对于5这个特殊键:如果最后一步走到5上,返回1;如果不是最后一步走到5上,那么就应该返回0,因为走不出去了,不能把所有步数都走完

总的来说,想到用图,然后写出邻接表,就好多了。memo只是之后的优化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值