知识点
乘法原理 动态规划
思路
下面我们讨论DP解法。
首先由于只能向右或者向下移动,那么说明任意值为2的点的横纵坐标大小关系必须是一致的,也就是对于点(x1,y1)和(x2,y2)而言,如果存在(x1 < x2)且 (y1 > y2)的情况一定是无解的
排除掉这一点后,我们发现假如存在m个有牛的位置,他会把整个图分成若干段,每一段都是求从左上角到右下角的方案数,而且互不干扰,这可以用乘法原理解决。而每一部分求从左上角到右下角的方法数是很基本的DP,和上一道题是一样的。
最差的时间复杂度应该是没有牛的时候从左上角到右下角,此时的时间复杂度是
AC Code (c++)
#define x first #define y second class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param cows int整型vector<vector<>> * @return int整型 */ using PII = pair<int, int>; vector<vector<int>> f; int uniquePathsWithCows(vector<vector<int> >& cows) { if (cows[0][0] == 1) return 0; int n = cows.size(), m = cows[0].size(); f.resize(n, vector<int>(m, 0)); vector<PII> pos; for (int i = 0; i < n; i ++) { for (int j = 0; j < m; j ++) { if (cows[i][j] == 2) { if (pos.size() and (pos.back().x > i or pos.back().y > j)) { return 0; } pos.emplace_back(i, j); } } } if (pos.empty() or pos.back() != make_pair(n - 1, m - 1)) { pos.emplace_back(n - 1, m - 1); } int res = 1; PII last = {0, 0}; for (auto& p: pos) { if (p == last) continue; res *= get(cows, last, p); last = p; cout << res << endl; } return res; } int get(vector<vector<int>>& g, const PII& st, const PII& ed) { for (int i = st.x; i <= ed.x; i ++) { for (int j = st.y; j <= ed.y; j ++) { if (i == st.x and j == st.y) { f[i][j] = 1; continue; } f[i][j] = 0; if (g[i][j] == 1) continue; if (i - 1 >= st.x) f[i][j] += f[i - 1][j]; if (j - 1 >= st.y) f[i][j] += f[i][j - 1]; } } return f[ed.x][ed.y]; } };