一、问题描述
二、问题分析
一开始想法跑偏,一直想着按照是否右交点进行问题分解尝试进行分治,(好像是有一道对角线的类似题),后来按交点分治不可行,无交点时计算不可再分,于是放弃。而后进行了DFS遍历,可行,代码如C/C++实现。进一步发现另一种子问题划分方式,如原书题解,将路径的第一步和最后一步进行讨论划分为小问题可以达到优化的目标,代码如Python实现。
三、代码实现
1.C/C++实现
#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cctype>
using namespace std;
const int MAX_M = 6;
const int MAX_N = 6;
const int det_x[] = { 0, 1, 0, -1 };
const int det_y[] = { 1, 0, -1, 0 };
typedef struct{
int x, y;
} Point;
// 对于边的标记沿用上一题思路
int h_flags[MAX_N + 1];
int v_flags[MAX_M + 1];
int get_path(Point cur, int left)
{
if (cur.x > MAX_M || cur.y > MAX_N || cur.x < 0 || cur.y < 0) // 越界
return 0;
if (left == 0 && cur.x == 0 && cur.y == 0) // 回到起点
return 1;
Point next;
int mask;
int count = 0;
// 重复代码可以优化
if (left > MAX_M + MAX_N) // 往
{
// 上
mask = 1 << cur.y;
if (!(v_flags[cur.x] & mask))
{
next.x = cur.x + det_x[0];
next.y = cur.y + det_y[0];
v_flags[cur.x] ^= mask;
count += get_path(next, left - 1);
v_flags[cur.x] ^= mask;
}
// 右
mask = 1 << cur.x;
if (!(h_flags[cur.y] & mask))
{
next.x = cur.x + det_x[1];
next.y = cur.y + det_y[1];
h_flags[cur.y] ^= mask;
count += get_path(next, left - 1);
h_flags[cur.y] ^= mask;
}
}
else // 返
{
// 下
mask = 1 << cur.y - 1;
if (!(v_flags[cur.x] & mask))
{
next.x = cur.x + det_x[2];
next.y = cur.y + det_y[2];
v_flags[cur.x] ^= mask;
count += get_path(next, left - 1);
v_flags[cur.x] ^= mask;
}
// 左
mask = 1 << cur.x - 1;
if (!(h_flags[cur.y] & mask))
{
next.x = cur.x + det_x[3];
next.y = cur.y + det_y[3];
h_flags[cur.y] ^= mask;
count += get_path(next, left - 1);
h_flags[cur.y] ^= mask;
}
}
return count;
}
int main()
{
// 书中以左上角开始到右下角,再回到左上角
// 这里从左下角开始到右上角,再回到左下角,显然两者等同
Point start{ 0, 0 };
memset(h_flags, 0, sizeof(h_flags));
memset(v_flags, 0, sizeof(v_flags));
cout << get_path(start, 2 * (MAX_M + MAX_N)) << endl;
return 0;
}
2.Python实现
# coding = utf-8
def get_path(x, y, t):
if x == 1:
count = t if y == t else t + 2
return count
if y == 1:
count = 2 if t == 0 else 1
return count
count = 0
if t == 0:
for i in range(0, y):
count += 2 * get_path(x - 1, y, i + 1)
else:
for i in range(t, y + 1):
count += get_path(x - 1, y, i)
count += get_path(x, y - 1, t - 1)
return count
if __name__ == '__main__':
print(get_path(6, 6, 0))
pass