算法設計與應用作業


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上歡迎交流~~~

對你有幫助就支付寶請我喝可樂叭~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM