IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 蓝桥杯 ALGO-1005 数字游戏 python -> 正文阅读

[数据结构与算法]蓝桥杯 ALGO-1005 数字游戏 python

蓝桥杯 ALGO-1005 数字游戏 python

试题 算法训练 数字游戏

资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。
  例如:
  3 1 2 4
  4 3 6
  7 9
  16
  现在如果知道N和最后得到的数字sum,请求出最初序列a[i],为1~N的一个排列。若有多种答案,则输出字典序最小的那一个。数据保证有解。

输入格式

第1行为两个正整数n,sum

输出格式

一个1~N的一个排列

样例输入

4 16

样例输出

3 1 2 4

数据规模和约定

0<n<=10

解题思路

其实这道题,我真的是跌宕起伏,如果是C++我可能早就写出来了吧,但是由于是python,很多解就不能暴力搜索了,要不然1-10的暴力搜索也不是不可以,孩子快哭了,不过无所谓,就当锻炼算法吧

首先给出两个70分的代码,在这两个code之中,都有一些比较好的思想,第一个就是可以直接利用我们内置库函数,对我们给出的数组进行一个全排列,然后我们直接累加迭代发现sum一样不就可以了么,这多么简单啊,还要搞什么呀哈哈哈,结果70分,有些案例就是过不了,时间直接TLE,让人绝望啊,先给出代码,代码思想很简单,就是得到全排列然后累加求和

内置库运用70分

import itertools
a = list(range(1,n+1))
n,sum = map(int,input().split())
for l in itertools.permutations(a,n):
     l = list(l)
     # print(l)
     l2 = l[:]
     for i in range(n-1):
         for j in range(n-1-i):
             l[j] += l[j+1]
             
     if l[0] == sum:
         for i in l2:
             print(i,end=' ')
         break

结果只有70分

然后行吧,用点算法吧,用搜索咯,那肯定是比较常见又简单的DFS咯,很简单的想法,我们可以在本身的数组上进行一个累加,这样最后得到的结果元素1也就是我们的s[0] 如果是sum的时候,我们就可以直接打印出结果了。

然后后面一段就是用dfs思想了,如果visit过了就换一个的,不断的迭代,直到有n个数据,我们才进行判断

DFS 70分

s = [0]*n
d = [0]*n
vis = [0]*n
n,sum = map(int,input().split())
def dfs(step):
    if step == n:
        s = d[:]
        for i in range(n-1):
            for j in range(n-1-i):
                s[j] += s[j+1]
        if s[0] == sum:
            print(' '.join(str(i) for i in d))
            return True
        else:
            return False

    for i in range(0,n):
        if vis[i] == 1:
            continue
        vis[i] = 1
        d[step] = i + 1
        if dfs(step+1):
            return True
        vis[i] = 0
    return False

dfs(0)

但是结果还是差强人意,虽然会比上面的时间复杂度低一点,但是还是70分啊,还有样例还是过不了,我差点绝望了,我就看啊看,到底有什么算法可以解决。其实对于我们的程序来说,最耗时间的一部分第一个是我们的赋值,我们的d赋值可以利用append,pop这些时间比较少的,其次就是我们求和那一部分是一个二重循环,时间复杂度比较高。

然后我就思前想去,突然,我在想,每一行中的数据求和与我们最后得到的和有什么关系么,后面,我终于悟到了,杨辉三角!!!

这不就是一个典型的杨辉三角么,按样例来看,杨辉三角的底层是1 3 3 1,求和就是3x1 + 1x3+ 2x3 + 4x1 = 16,哇,这么说的话,其实我并不用算太多,我可以直接进行一个计算杨辉三角的底层,只有一个循环,这就简单了

在这里插入图片描述

所以首先小小改进了一下

改进的90分代码

# return 杨辉三角的最后一行
def yh(num):
    if num == 1:
        res = [1]
    else:
        res = [[0]*num for i in range(num)]
        for i in range(num):
            for j in range(num):
                res[i][0] = 1
                if i == j:
                    res[i][j] = 1
        for i in range(2,num):
            for j in range(1,i):
                res[i][j] = res[i-1][j-1] + res[i-1][j]
    return res[num-1]

n,sum = map(int,input().split())
yh = yh(n)

d = [0]*n
vis = [0]*n

def dfs(step):
    if step == n:
        s = 0
        for i in range(n):
            s += d[i]*yh[i]        
        if s == sum:
            print(' '.join(str(i) for i in d))
            return True
        else:
            return False

    for i in range(0,n):
        if vis[i] == 1:
            continue
        vis[i] = 1
        d[step] = i + 1
        if dfs(step+1):
            return True
        vis[i] = 0
    return False
if n == 1:
    print(sum)
else:
	dfs(0)

结果还是大意了,只有80,所以其实在我们的DFS中,我们还需要一些剪枝之类的操作才可以得到比较好的结果,所以用同样的想法进行一个改进,最后终于圆满了,我们可以在本身要计算的时候,传入的就是求和的结果,如果大于我们需要的sum就直接break,也就是剪枝了,这样可能就比较好,减少了循环的计算。

完美的100分代码

# return 杨辉三角的最后一行
def yh(num):
    if num == 1:
        res = [1]
    else:
        res = [[0]*num for i in range(num)]
        for i in range(num):
            for j in range(num):
                res[i][0] = 1
                if i == j:
                    res[i][j] = 1
        for i in range(2,num):
            for j in range(1,i):
                res[i][j] = res[i-1][j-1] + res[i-1][j]
    return res[num-1]

n,sum = map(int,input().split())
yh = yh(n)

d = []
vis = [0]*(n+1)

def dfs(step,s):
    if s > sum:
        return False
    if step == n:
        if s == sum:
            print(' '.join(str(i) for i in d))
            return True
        else:
            return False

    for i in range(1,n + 1 ):
        if vis[i] == 0:
            vis[i] = 1
            d.append(i)
            if dfs(step+1,s+yh[step]*i):
                return True
            vis[i] = 0
            d.pop()
    return False
if n == 1:
    print(sum)
else:
    dfs(0,0)

所以最后终于AC了,结束了,good,还好成功了,没有放弃

每日一句

What doesn’t kill you makes you stronger.

没能摧毁你的,必使你强大。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 10:09:32  更:2021-11-27 10:10:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/29 5:33:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码