蓝桥杯寒假作业(递归生成全排列)

1. 问题描述:

现在小学的数学题目也不是那么好玩的。 看看这个寒假作业: 

每个方块代表1~13中的某一个数字,但不能重复。 比如: 

6  + 7 = 13 
9  - 8 = 1 
3  * 4 = 12 
10 / 2 = 5 

以及:  
7  + 6 = 13 
9  - 8 = 1 
3 * 4 = 12 
10 / 2 = 5 

就算两种解法。(加法,乘法交换律后算不同的方案) 
你一共找到了多少种方案? 

输出

请填写表示方案数目的整数。 

来源:http://oj.ecustacm.cn/problem.php?id=1285

2. 思路分析:

分析题目可以知道我们可以将1-13个数字填入到方块中看是否满足题目中四个算式中的运算,所以需要尝试所有的可能性,一个比较容易想到的方法是递归生成全排列,然后将数字填到方格中看是否满足条件,下面使用的是for循环中交换列表(python语言使用列表,c/c++/java语言使用数组)中的元素递归生成全排列,在递归的出口依次判断对应位置的数字经过运算之后是否相等,如果四个等式运算的结果都满足那么计算加1,最终输出计数的结果即可。使用python语言很久都计算不出来,后面转换为java语言使用相同的思路计算出结果为64(java也需要等待几十秒),并且在递归的出口可以输出对应的列表中元素的值看是否正确。

3. 代码如下:

python代码(没有计算出最终的结果):

from typing import List

res = 0


def permutation(index: int, nums: List[int]):
    # 属于global关键字修改全局变量
    global res
    if index == 13:
        # 判断是否满足要求
        if nums[0] + nums[1] != nums[2]: return
        if nums[3] - nums[4] != nums[5]: return
        if nums[6] * nums[7] != nums[8]: return
        if nums[9] != nums[10] * nums[11]: return
        res += 1
        return
    for i in range(index, 13):
        # 交换元素递归生成全排列
        t = nums[i]
        nums[i] = nums[index]
        nums[index] = t
        permutation(index + 1, nums)
        # 回溯, 将元素交换回去
        t = nums[i]
        nums[i] = nums[index]
        nums[index] = t


if __name__ == '__main__':
    nums = [i for i in range(1, 14)]
    permutation(0, nums)
    print(res)

java代码:

public class Main {
    public static void main(String[] args) {
        int nums[] = new int[13];
        for (int i = 1; i < 14; ++i){
            nums[i - 1] = i;
        }
        permutation(0, nums);
        System.out.println(res);
    }

    static int res = 0;
    public static void permutation(int index, int []nums){
        if (index == 13){
            if (nums[0] + nums[1] != nums[2]) return;
            if (nums[3] - nums[4] != nums[5]) return;
            if (nums[6] * nums[7] != nums[8]) return;
            // 转换为乘法可以避免精度的问题
            if (nums[11] * nums[10] != nums[9]) return;
            for (int i = 0; i < 13; ++i){
                System.out.print(nums[i] + " ");
            }
            System.out.println();
            res += 1;
            return;
        }
        for (int i = index; i < 13; ++i){
            int t = nums[i];
            nums[i] = nums[index];
            nums[index] = t;
            permutation(index + 1, nums);
            //回溯
            t = nums[i];
            nums[i] = nums[index];
            nums[index] = t;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值