軍訓隊列
題目描述
某大學開學進行軍訓隊列訓練,將學生從一開始按順序依次編號,並排成一行橫隊,訓練的規則如下:從頭開始一至二報數,凡報到二的出列剩下的依次向前靠攏,再從頭開始進行一至三報數,凡報到三的出列,剩下的依次向前靠攏,繼續從頭開始進行一至二報數。。。以后每次從頭開始輪流進行一至二報數、一至三報數直到剩下的人數不超過三人為止。
輸入
第一行為組數N,接着為N行學生人數,學生人數不超過5000。
樣例輸入
2
20
40
輸出
輸出有N行,分別對應輸入的學生人數,每行輸出剩下的學生最初的編號,編號之間有一個空格。
樣例輸出
1 7 19
1 19 37
時間限制
C/C++語言:1000MS其它語言:3000MS
內存限制
C/C++語言:65536KB其它語言:589824KB
試題地址:http://exercise.acmcoder.com/online/online_judge_list_all
在賽碼網上做算法題,遇到這樣一道題。
我的能力雖然一般,還需要繼續努力才能進步。
但是希望記錄下來學會一道題的想法,可以提供給一些沒有思路的朋友們一個參考!
代碼捉襟見肘,還請見諒~
這是一道動態規划的題。
動態規划大致的思路就是:
把一個龐大的問題每次只完成一小步,每次都得到一個階段的結果,然后用這個結果去當作下一階段的開始狀態。
並且每一步都是一個決策,不會影響接下來階段的決策,每個階段是獨立的。
我的思路是:
1 根據輸入人數m,初始化一個數組list,下標從0到m-1號依次存入1到m號,表示他們的編號
2 開啟一個新的隊列res,對list進行1至2報數:
把list所有報1的位置里面的值依次入隊列res,一直到list遍歷結束
執行3:對res 進行1至3報數
3 對res進行1至3報數:
開啟一個隊列res2
把所有喊1和2的位置的元素依次入隊列到res2中 一直到res隊列遍歷結束
執行2:在對res2進行1至2報數
。。。。
最終,當結果隊列里面少於三個元素時候,結束,得到了結果!
我是用python3來實現的:
1 # coding:utf8
2 #list是當前隊列里按順序排號的編號,step是本次要執行1到幾報數
3 def result(list, step): 4 if len(list) <= 3: #如果不多於3人,則應該返回結果
5 return list 6 res = [] #用於存儲結果
7 if step == 2: #如果是1到2報數
8 res = list[::2] # 把list里的所有報2的人踢出去,剩下1 的人存給新列表res
9 return result(res, 3) #遞歸調用:再對res進行1到3報數
10 else: #否則 當前是1到3報數
11 cur = 0 #臨時變量 表示當前所在0號位置 我們進行向下遍歷操作
12 while cur < len(list): #如果當前還沒到隊尾
13 res.append(list[cur]) #把當前這個人放到res里
14 if cur + 1 < len(list): 15 res.append(list[cur + 1]) #把這個人的下一個人也放res里
16 cur += 3 #cur向后移動3人的位置
17 #跳出循環后,我們把報1和2 的人都放進了res,在對res進行1到2報數
18 return result(res, 2) 19 #這樣一直遞歸調用,每次都新開一個res來存留下來的人,一直到res里小於等於3個人的時候就是結果。
20
21
22 def main(): 23 n = int(input()) #接收測試用例數
24 for i in range(n): #每一次測試用例都做的
25 m = int(input()) #接收一個隊列人數
26 list = [j for j in range(1, m + 1)] #一個列表,從0到m-2 每個位置里面存了人的編號1到m
27 #調用方法得到列表,把列表轉換成符合題目要求的字符串
28 res = str(result(list, 2)).lstrip("[").rstrip("]").replace(",", " ") 29 print(res) 30
31
32 if __name__ == '__main__': 33 main()