Fork me on GitHub

算法设计与应用作业

CCNU算法设计作业,仅供参考0.0

自己动手,丰衣足食QAQ更新全看心情

 

Task-1

1.输入一个自然数(<90000),  分别用递归法和非递归法求其二进制表示.

# -*- coding: utf-8 -*- 
# @Time : 2019/10/10 21:29 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : binary.py 
# @Software: PyCharm

#recursion
def recursion(n):
    result = ''
    if n == 0:
        return result
    else:
        result = recursion(n//2)
        return result + str(n%2)

num_a = int(input("input a decimal number : "))

if num_a >= 90000:
    print("error!")
else:
    print(recursion(num_a))



#non-recursion

def non_recursion(n):
    s = ''
    while n > 0:
        s = str(n%2) + s    # 取余后更新 s
        n = n//2            # 取整后更新 n
    return s
num_b = int(input("input another decimal number : "))

if num_b >= 90000:
    print("error!")
else:
    print(non_recursion(num_b))

 运行截图:

考虑边界情况

 随机数情况

 

2.  分别用递归法和非递归法求Fibonacci数列的前1000位,并比较计算时间的差异.

# -*- coding: utf-8 -*- 
# @Time : 2019/10/11 0:25 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : Fibonacci.py 
# @Software: PyCharm
import time

#recursion
def fib_recursion(n):
    if  n == 1:
        return 1
    elif n == 2:
        return 1
    else:
        return fib_recursion(n-1) + fib_recursion(n-2)

num_a = int(input("input a number : "))
tic = time.process_time()
if num_a==0:
    print("error!")
else:
    print(fib_recursion(num_a))
    toc = time.process_time()
    print("time : "+ str(1000*(toc-tic)))



#non_recursion
def fib_loop(n):
    a = 0
    b = 1
    c = 0
    for i in range(n):
        c = a + b
        a = b
        b = c
    return a

num_b = int(input("input a number : "))
tic = time.process_time()
if num_b==0:
    print("error!")
else:
    print(fib_loop(num_b))
    toc = time.process_time()
    print("time : " + str(1000 * (toc - tic))) 


#another method
class Fibonacci(object):
    '''
    斐波那契数列迭代器
    '''
    def __init__(self,n):
        '''

        :param n: int 指的是生成数列的个数
        '''
        self.n = n
        #保存当前生成的数列的第几个数据 生成器中性质,记录位置,下一个位置的数据
        self.current = 0
        self.a = 0
        self.b = 1

    def __next__(self):
        '''

        :return:当前使用next()函数调用时,就会获取下一个数
        '''
        if self.current<self.n:
            self.a,self.b = self.b,self.a+self.b
            self.current +=1
            return self.a
        else:
            raise StopIteration

    def __iter__(self):
        '''

        :return: 迭代器的__iter__返回自身即可
        '''
        return self

if __name__ == '__main__':
    num_c = int(input("input a number : "))
    fib = Fibonacci(num_c)
    for n in fib:
        print(n)

 运行截图:

 

 

当计算第1000个数的时候会报错,超过最大递归深度。但是经过其他随机测试可得codes并无错误,但是该怎么解决还在思考中。尝试进行第999个数的计算可行,计算时间超长。

利用datatime模块可以计算并比较递归与非递归的时间差异。

e.g. input a number:35 //已经时间放大1000倍便于观察比较。

 

 /*后记*/老师要求只求出第50个斐波那契数即可,其实50层迭代的斐波那契数的计算也需要非常多的时间。以30层斐波那契数的计算时间为5s为基础。第50个斐波那契数的计算时间是第30个数的计算的1048,576倍。i7-7700HQ大概需要计算145小时。(当然可能是我计算失误,不是这个时间)

 

3.递归算法完成如下问题:有52张牌,使它们全部正面朝上,第一轮是从第2张开始,凡是2的倍数位置上的牌翻成正面朝下;第二轮从第3张牌开始,

凡是3的倍数位置上的牌,正面朝上的翻成正面朝下,正面朝下的翻成正面朝上;第三轮从第4张牌开始,凡是4的倍数位置上的牌按上面相同规则翻转,

以此类推,直到第一张要翻的牌超过52为止。统计最后有几张牌正面朝上,以及它们的位置号.

# -*- coding: utf-8 -*- 
# @Time : 2019/10/11 18:42 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : card.py 
# @Software: PyCharm

#non_recursion
s = [0]*52
print("initial state : ",s,"\n")

for i in range(1,52):
    for j in range(i,52):
        if((j+1)%(i+1)==0):
            if(s[j]==0):
                s[j]=1
            else:
                s[j]=0

print("ending state : ",s,"\n")

vec = [x+1 for x in range(52) if s[x]==0]
print("index : ",vec,"\n")

#recursion
s = [0]*52
print("initial state : ",s,"\n")

def turn_card(n):
    if(n>52):
        return
    else:
        for j in range(n,52):
            if ((j + 1) % (n + 1) == 0):
                if (s[j] == 0):
                    s[j] = 1
                else:
                    s[j] = 0
        turn_card(n+1)

turn_card(1)

print("ending state : ", s, "\n")

vec = [x+1 for x in range(52) if s[x]==0]
print("index : ",vec,"\n")

 运行截图:

 

4.一个射击运动员打靶,靶一共有10环,连开6枪打中45环的可能性有多少种? (每一枪最少是0环,最多是10环)

# -*- coding: utf-8 -*- 
# @Time : 2019/10/12 11:29 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : shooting.py 
# @Software: PyCharm

times = 0
def shooting(n,sum):
    global  times
    if n<0:
        return
    elif (45 - sum)>(10*(n)):
        return
    elif (sum == 45) and (n == 0):
        times += 1
        return
    for i in range(11):
        shooting(n - 1,sum + i)

shooting(6,0)

print('there are %d possibilities'%times)

 运行截图:

 

5.8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,输出所有摆法。

# -*- coding: utf-8 -*- 
# @Time : 2019/10/12 17:00 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : queens.py 
# @Software: PyCharm
def is_rule(queen_tup, new_queen):
    """
    :param queen_tup: 棋子队列,用于保存已经放置好的棋子,数值代表相应棋子列号
    :param new_queen: 被检测棋子,数值代表列号
    :return: True表示符合规则,False表示不符合规则
    """
    num = len(queen_tup)
    for index, queen in enumerate(queen_tup):

        if new_queen == queen:  # 判断列号是否相等
            return False
        if abs(new_queen - queen) == num - index:  # 判断列号之差绝对值是否与行号之差相等
            return False

    return True


def arrange_queen(num, queen_tup=list()):
    """
    :param num:棋盘的的行数,当然数值也等于棋盘的列数
    :param queen_tup: 设置一个空队列,用于保存符合规则的棋子的信息
    """

    for new_queen in range(num):  # 遍历一行棋子的每一列

        if is_rule(queen_tup, new_queen):  # 判断是否冲突

            if len(queen_tup) == num - 1:  # 判断是否是最后一行
                yield [new_queen]  # yield关键字

            else:
                # 若果不是最后一行,递归函数接着放置棋子
                for result in arrange_queen(num, queen_tup + [new_queen]):
                    yield [new_queen] + result


for i in arrange_queen(8):
    print(i) 

运行截图(部分):

 

Task-2

迷宫问题:设有8*8的方格迷宫,入口和出口分别在左上角和右上角,迷宫格子中分别有0和1,1代表不能走,

迷宫走的规则如图。当迷宫给出后,找到一条从入口到出口的通路。

 源代码:

 

 -*- coding: utf-8 -*-
# @Time : 2019/10/19 10:26
# @Author : BaoBao
# @Mail : baobaotql@163.com
# @File : mzae.py
# @Software: PyCharm
import numpy as np

maze =np.array ([
    [0, 0, 0, 0, 0, 0, 1, 0],
    [1, 0, 1, 1, 1, 1, 1, 0],
    [0, 1, 0, 0, 1, 0, 0, 1],
    [0, 0, 1, 1, 0, 1, 0, 1],
    [0, 1, 0, 0, 0, 1, 1, 0],
    [0, 1, 1, 1, 1, 1, 0, 1],
    [0, 0, 1, 1, 1, 0, 1, 1],
    [1, 1, 0, 0, 1, 0, 0, 0],
])

p = np.array([1, 1, 1, 1, 1, 1, 1, 1])
q = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

a = np.insert(maze, 0, values=p, axis=1)
b = np.insert(a, 9,values=p, axis=1)

c = np.insert(b, 0, values=q, axis=0)
d = np.insert(c, 9, values=q, axis=0)

print("初始化迷宫:")
print(d)#为解决越界问题 初始化迷宫

dirs = [lambda x, y: (x + 1, y),
        lambda x, y: (x - 1, y),
        lambda x, y: (x, y - 1),
        lambda x, y: (x, y + 1),
        lambda x, y: (x + 1, y - 1),
        lambda x, y: (x + 1, y + 1),
        lambda x, y: (x - 1, y - 1),
        lambda x, y: (x - 1, y + 1)
        ]

def mpath(x1, y1, x2, y2):
    stack = []      #建立抽象栈
    stack.append((x1, y1))      #加入初始点
    d[x1][y1] = -1       #表示已经走过
    while len(stack) > 0:
        curNode = stack[-1]
        if curNode == (x2, y2):
            print(stack)
            return True

        for dir in dirs:
            nextNode = dir(curNode[0], curNode[1])
            if d[nextNode[0]][nextNode[1]] == 0 : #找到了下一个
                stack.append(nextNode)
                d[nextNode[0]][nextNode[1]] = -1  # 标记为已经走过,防止死循环
                break

        else:   #八个方向都没找到
            d[curNode[0]][curNode[1]] = -1  # 死路一条,标记下次不走
            stack.pop()  #回溯

    print("没有路")
    return False

mpath(1,1,8,8)

运行截图:

 

Task-3

1.利用动态规划算法求解编辑距离问题,给定两个字符串,求由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符

# -*- coding: utf-8 -*- 
# @Time : 2019/12/1 17:25 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : Edit_Distance.py 
# @Software: PyCharm
'''
利用动态规划算法求解编辑距离问题
'''
def minDistance(word1, word2):
    '''

    :param word1: 传入字符串word1
    :param word2: 传入字符串Word2
    :return: 返回距离矩阵元素
    '''
    m = len(word1)
    n = len(word2)
    if m == 0:
        return n
    if n == 0:
        return m
    dp = [[0] * (n+1) for _ in range(m+1)] #初始化表格[m+1, n+1]
    # 计算边界
    for i in range(1, m+1):
        dp[i][0] = i
    for j in range(1, n+1):
        dp[0][j] = j
    for i in range(1, m+1): #计算dp
        for j in range(1, n+1):
            if word1[i-1] == word2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            else:
                dp[i][j] = min(dp[i-1][j-1]+1, dp[i][j-1]+1, dp[i-1][j]+1)
    return dp[m][n]


if __name__ == "__main__":
    dis = minDistance('www.ccnu.edu.cn', 'www.neu.edu.cn')
    print("The longest Edit Distance is :", dis)

运行截图

 

 

2.用动态规划算法求最长公共子序列问题.

# -*- coding: utf-8 -*- 
# @Time : 2019/12/1 17:32 
# @Author : BaoBao
# @Mail : baobaotql@163.com 
# @File : LCS.py 
# @Software: PyCharm

import numpy as np

def Longest_Common_Subsequence(a, b):
    '''

    :param a:字符串a
    :param b:字符串b
    :return:length
            subseq
    '''
    length = 0
    subseq = ''
    cell = np.zeros(shape=(len(a), len(b)))
    for i in range(len(a)):
        for j in range(len(b)):
            if a[i] == b[j]:
                cell[i][j] = cell[i - 1][j - 1] + 1
                if cell[i][j] > length:
                    length = cell[i][j]
                    subseq += a[i]
            else:
                cell[i][j] = max(cell[i-1][j], cell[i][j-1])
    return length, subseq

if __name__ == "__main__":
    a, b = Longest_Common_Subsequence('www.ccnu.edu.cn', 'www.neu.edu.cn')
    print('The length of longest common subsequence is:%d\nThe Longest Common Subsequence is:%s' % (a, b))

运行截图

 

 

 

算法分析在本人github上欢迎交流~~~

对你有帮助就支付宝请我喝可乐叭~~~

posted @ 2019-10-13 16:24  鲍鲍tql  阅读(617)  评论(0编辑  收藏  举报