摘要:能以最少交換次數(shù)到達(dá)升序有序排列記為的數(shù)列記為就等價(jià)于從代表的節(jié)點(diǎn)在這張圖中到達(dá)對(duì)應(yīng)的節(jié)點(diǎn)的最短路徑長(zhǎng)度。上一篇質(zhì)數(shù)矩陣質(zhì)數(shù)矩陣下一篇唯一的序列本系列總目錄參見(jiàn)程序員的算法趣題詳細(xì)分析和全解程序員的算法趣題詳細(xì)分析和全解
目錄
????????考慮:N個(gè)數(shù)字的每種排列看作是一個(gè)節(jié)點(diǎn),鄰節(jié)點(diǎn)是指能通過(guò)交換任意兩個(gè)位置的數(shù)得到的新的排列。這樣,所有N!個(gè)排列一個(gè)連通圖。能以最少交換次數(shù)到達(dá)升序有序排列(記為B)的數(shù)列(記為A)就等價(jià)于從A代表的節(jié)點(diǎn)在這張圖中到達(dá)B對(duì)應(yīng)的節(jié)點(diǎn)的最短路徑長(zhǎng)度。
????????進(jìn)一步,“交換任意兩個(gè)位置的數(shù)”是可逆的操作,這是一個(gè)無(wú)向圖。因此,從節(jié)點(diǎn)A到達(dá)節(jié)點(diǎn)B的最短路徑長(zhǎng)度,等于從節(jié)點(diǎn)B到達(dá)節(jié)點(diǎn)A的最短路徑長(zhǎng)度。
????????所以本題求解的其實(shí)就是在這種圖中,從節(jié)點(diǎn)B點(diǎn)其它所有各節(jié)點(diǎn)的最短路徑長(zhǎng)度之和。而求最短路徑長(zhǎng)度的標(biāo)準(zhǔn)解法就是廣度優(yōu)先搜索。從節(jié)點(diǎn)B出發(fā)通過(guò)廣度優(yōu)先搜索遍歷所有節(jié)點(diǎn),記錄下每個(gè)節(jié)點(diǎn)的層數(shù)(距離),最后求和即可。
????????廣度優(yōu)先搜索(BFS)的基本流程(即便在本系列也出現(xiàn)過(guò)了很多次)這里就不再贅述(不熟悉的伙伴可以參閱前面的題解)。
????????在一般的BFS流程中,用visited只需要記錄已訪問(wèn)過(guò)的節(jié)點(diǎn),而無(wú)需記錄其對(duì)應(yīng)的距離。本題解在最后統(tǒng)一進(jìn)行距離求和,所以必須將每個(gè)節(jié)點(diǎn)的距離記錄下來(lái),最自然的做法當(dāng)然是在visited中將節(jié)點(diǎn)和距離信息一起記錄下來(lái),因此在本題解中用dict()實(shí)現(xiàn)visited(一般只記憶節(jié)點(diǎn)的話用set()即可)。
# -*- coding: utf-8 -*-"""Created on Tue Sep 28 07:50:03 2021@author: chenxy"""import sysimport timeimport datetimeimport math# import randomfrom typing import List# from queue import Queuefrom collections import dequeimport itertools as itimport numpy as npN = 7q = deque()visited = dict()q.append((tuple(range(N)),0))visited[tuple(range(0,N))] = 0tStart = time.perf_counter()while len(q) > 0: cur,layer = q.popleft() for c2 in it.combinations(range(N), 2): nxtlst = list(cur) nxtlst[c2[0]],nxtlst[c2[1]] = nxtlst[c2[1]],nxtlst[c2[0]] nxt = tuple(nxtlst) if nxt not in visited: visited[nxt] = layer + 1 q.append((nxt,layer+1))count = 0for key in visited: count += visited[key]tCost = time.perf_counter() - tStartprint("N = {0}, count={1}, tCost = {2:6.3f}(sec)".format(N,count,tCost))
????????運(yùn)行結(jié)果:N = 7, count=22212, tCost = ?0.073(sec)
????????原書還給出兩個(gè)更簡(jiǎn)單的解法。
????????其一的思路是:某排列與最終升序排列中位置一致的數(shù)字不需要再參與交換,所以只需要找出和初始狀態(tài)下的位置不同的數(shù)字進(jìn)行交換就可以了。
? ? ? ? 其二的思路是利用數(shù)學(xué)上對(duì)稱群的概念,通過(guò)循環(huán)置換的乘積來(lái)求解。
? ? ? ? 前一個(gè)還好理解(問(wèn)題在于能不能想到這一點(diǎn)),后一個(gè)需要群的知識(shí)為基礎(chǔ)。容我再學(xué)習(xí)學(xué)習(xí)品一品后再來(lái)補(bǔ)充題解。
? ? ? ? 上一篇:Q44: 質(zhì)數(shù)矩陣
? ? ? ? 下一篇:Q46: 唯一的OX序列
????????本系列總目錄參見(jiàn):程序員的算法趣題:詳細(xì)分析和Python全解
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121525.html
摘要:可以在遍歷所有矩陣時(shí),對(duì)各種出現(xiàn)的次數(shù)進(jìn)行計(jì)數(shù),最后計(jì)數(shù)值為的個(gè)數(shù)即為所求結(jié)果。上一篇排序交換次數(shù)的最少化排序交換次數(shù)的最少化本系列總目錄參見(jiàn)程序員的算法趣題詳細(xì)分析和全解程序員的算法趣題詳細(xì)分析和全解 目錄 1. 問(wèn)題描述 2. 解題分析 3. 代碼及測(cè)試 4. 后記 1. 問(wèn)題描述 ...
摘要:中的統(tǒng)一的終點(diǎn)是全白狀態(tài)。比如說(shuō),的第個(gè)數(shù)恰好是,它可以由根據(jù)題設(shè)規(guī)則重排而得。上一篇填充白色填充白色下一篇優(yōu)雅的地址本系列總目錄參見(jiàn)程序員的算法趣題詳細(xì)分析和全解程序員的算法趣題詳細(xì)分析和全解 目錄 1. 問(wèn)題描述 2. 解題分析 2.1??Naive Approach--正向全量搜索 ...
摘要:漢明距離可以用異或操作實(shí)現(xiàn)。這個(gè)問(wèn)題其實(shí)可以看作是,具有個(gè)節(jié)點(diǎn)的全連接無(wú)向圖,每條邊的權(quán)重值代表兩個(gè)節(jié)點(diǎn)所代表的數(shù)字的段碼顯示的二進(jìn)制表示之間的漢明距離。 目錄 1. 問(wèn)題描述 2. 解題分析 3. 代碼及測(cè)試 1. 問(wèn)題描述 ????????問(wèn)題:求把10個(gè)數(shù)字全部顯示出來(lái)時(shí),亮燈/滅...
摘要:但是由于不能使用作為,所以將表示狀態(tài)的列表轉(zhuǎn)換為后再用作的。上一篇將牌洗為逆序下一篇糖果惡作劇本系列總目錄參見(jiàn)程序員的算法趣題詳細(xì)分析和全解 目錄 1. 問(wèn)題描述 2. 解題分析 2.1?節(jié)點(diǎn)狀態(tài)表示 ???????2.2?鄰節(jié)點(diǎn)搜索 ???????2.3?路徑歷史記憶以及判斷鄰節(jié)點(diǎn)是否在...
摘要:目錄前言前言遞推關(guān)系遞推關(guān)系代碼及測(cè)試代碼及測(cè)試后記后記前言參見(jiàn)程序員的算法趣題偷懶的算盤上一篇中給出的初始方案是暴力破解或者說(shuō)全量搜索的方式,總共需要搜索種情況,因此非常耗時(shí)。 目錄 1. 前言 2. 遞推關(guān)系 3. 代碼及測(cè)試 4. 后記 1. 前言 ????????參見(jiàn)程序員的算法趣...
閱讀 665·2021-11-23 09:51
閱讀 3611·2021-11-15 11:38
閱讀 943·2021-10-14 09:42
閱讀 3190·2021-09-29 09:35
閱讀 2126·2021-09-03 10:33
閱讀 780·2021-07-30 16:33
閱讀 1569·2019-08-30 15:55
閱讀 1855·2019-08-30 14:04