算法趣题-Q31

一、问题描述

 

二、问题分析

        一开始想法跑偏,一直想着按照是否右交点进行问题分解尝试进行分治,(好像是有一道对角线的类似题),后来按交点分治不可行,无交点时计算不可再分,于是放弃。而后进行了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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值