国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【動態(tài)規(guī)劃】【廣度優(yōu)先搜索】【狀態(tài)壓縮】847 訪問所有節(jié)點的最短路徑

這篇具有很好參考價值的文章主要介紹了【動態(tài)規(guī)劃】【廣度優(yōu)先搜索】【狀態(tài)壓縮】847 訪問所有節(jié)點的最短路徑。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

作者推薦

視頻算法專題

本文涉及知識點

動態(tài)規(guī)劃匯總
廣度優(yōu)先搜索 狀態(tài)壓縮

LeetCode847 訪問所有節(jié)點的最短路徑

存在一個由 n 個節(jié)點組成的無向連通圖,圖中的節(jié)點按從 0 到 n - 1 編號。
給你一個數(shù)組 graph 表示這個圖。其中,graph[i] 是一個列表,由所有與節(jié)點 i 直接相連的節(jié)點組成。
返回能夠訪問所有節(jié)點的最短路徑的長度。你可以在任一節(jié)點開始和停止,也可以多次重訪節(jié)點,并且可以重用邊。
示例 1:
輸入:graph = [[1,2,3],[0],[0],[0]]
輸出:4
解釋:一種可能的路徑為 [1,0,2,0,3]
示例 2:
輸入:graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
輸出:4
解釋:一種可能的路徑為 [0,1,4,2,3]
參數(shù)范圍
n == graph.length
1 <= n <= 12
0 <= graph[i].length < n
graph[i] 不包含 i
如果 graph[a] 包含 b ,那么 graph[b] 也包含 a
輸入的圖總是連通圖

廣度優(yōu)先搜索

需要記錄那些節(jié)點已經(jīng)訪問,用狀態(tài)壓縮 (1 << i )表示第i個節(jié)點已訪問。
還要記錄此路徑的最后節(jié)點。
這兩個狀態(tài)相同,后面的路徑則相同。 由于是廣度優(yōu)先搜索,所以路徑短的先處理,每個狀態(tài)只會處理一次。
vDis 記錄各狀態(tài)的最短路徑數(shù)。
que 記錄狀態(tài)。
時間復雜度:O(n2nn) 枚舉起點O(n) 枚舉狀態(tài)數(shù)O(2^n) 每個狀態(tài)處理。

核心代碼

class Solution {
public:
	int shortestPathLength(vector<vector<int>>& graph) {
		m_c = graph.size();
		m_iMaskCount = 1 << m_c;
		for (int i = 0; i < m_c; i++)
		{
			BFS(graph, i);
		}
		return m_iRet;
	}
	void BFS(vector<vector<int>>& neiBo,int start)
	{
		vector<vector<int>> vDis(m_c, vector<int>(m_iMaskCount, m_iNotMay));
		queue<pair<int, int>> que;
		auto Add = [&](int node, int iPreMask,int iNew)
		{
			const int iMask = iPreMask | (1 << node);
			if (vDis[node][iMask] <= iNew )
			{
				return ;
			}
			vDis[node][iMask] = iNew;
			que.emplace(node, iMask);
		};
		Add( start,0, 0);
		while (que.size())
		{
			auto [preNode, preMask] = que.front();
			const int iNew = vDis[preNode][preMask]+1;
			que.pop();
			for (const auto& next : neiBo[preNode])
			{
				Add(next, preMask, iNew);
			}
		}
		for (const auto& v : vDis)
		{
			m_iRet = min(m_iRet, v.back());
		}
	}
	const int m_iNotMay = 100'000;
	int m_c, m_iMaskCount;
	int m_iRet = m_iNotMay;
};

測試用例

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{	
	vector<vector<int>> graph;
	{
		Solution sln;
		graph = { {1,2,3},{0},{0},{0} };
		auto res = sln.shortestPathLength(graph);
		Assert(res, 4);
	}

	{
		Solution sln;
		graph = { {1},{0,2,4},{1,3,4},{2},{1,2} };
		auto res = sln.shortestPathLength(graph);
		Assert(res, 4);

	}
	
}

動態(tài)規(guī)劃

節(jié)點的距離用多源路徑的最短距離。

動態(tài)規(guī)劃的狀態(tài)表示

mask&(1 << next)表示經(jīng)過了next節(jié)點。
vDis[node][mask] 有以下兩種含義:
一, 以node結尾,經(jīng)過mask指定節(jié)點的最短路徑經(jīng)過的節(jié)點數(shù)。
二,以node結尾,且只經(jīng)過node節(jié)點一次,經(jīng)過mask指定節(jié)點的最短路徑經(jīng)過的節(jié)點數(shù)。
含義二,如果存在,則是含義二,否則是含義一。 必須枚舉所有符合含義二的可能。

動態(tài)規(guī)劃的轉移方程

vDis[next][maks|next]= MinSelf n e x t = 0 m c ? 1 \Large_{next=0}^{m_c-1} next=0mc??1?vDis[i][mask]+距離(i,next)
vDis[i][mask] 必須合法,且mask不包括next節(jié)點

動態(tài)規(guī)劃的填表順序

mask從1到大,確保動態(tài)規(guī)劃的無后效性。某路徑的編碼是mask,經(jīng)過新節(jié)點next后,新編碼為iNewMask。則iNewMask-mask = 1 << next
1 << next 恒大于0。

動態(tài)規(guī)劃的初始值

全部為不存在的數(shù)

動態(tài)規(guī)劃的返回值

Min j = 0 m c ? 1 \Large_{j=0}^{m_c-1} j=0mc??1?vDis[j].back() -1

證明

將最短路徑的重復節(jié)點刪除,保留任意一個。刪除后為: i 1 \Large_1 1? i 2 \Large_2 2? …i n \Large_n n? 。任意i k \Large_k k?到i k + 1 \Large_{k+1} k+1?的路徑一定是最短,否則替換成最短。直接枚舉,12! 超時。 用動態(tài)規(guī)劃,共2nn種狀態(tài),空間復雜度O(2nn),每種狀態(tài)轉移時間復雜度O(n),故總時間復雜度O(2nnn)。

代碼

//多源碼路徑
template<class T, T INF = 1000 * 1000 * 1000>
class CFloyd
{
public:
	CFloyd(const  vector<vector<T>>& mat)
	{
		m_vMat = mat;
		const int n = mat.size();
		for (int i = 0; i < n; i++)
		{//通過i中轉
			for (int i1 = 0; i1 < n; i1++)
			{
				for (int i2 = 0; i2 < n; i2++)
				{
					//此時:m_vMat[i1][i2] 表示通過[0,i)中轉的最短距離
					m_vMat[i1][i2] = min(m_vMat[i1][i2], m_vMat[i1][i] + m_vMat[i][i2]);
					//m_vMat[i1][i2] 表示通過[0,i]中轉的最短距離
				}
			}
		}
	};
	vector<vector<T>> m_vMat;
};

class Solution {
public:
	int shortestPathLength(vector<vector<int>>& graph) {
		m_c = graph.size();
		m_iMaskCount = 1 << m_c;
		vector<vector<int>> mat(m_c, vector<int>(m_c, 1000 * 1000 * 1000));
		for (int i = 0; i < m_c; i++)
		{
			for (const auto& j : graph[i])
			{
				mat[i][j] = 1;
			}
		}
		CFloyd floyd(mat);
		vector<vector<int>> vDis(m_c, vector<int>(m_iMaskCount, m_iNotMay));
		for (int i = 0; i < m_c; i++)
		{	
			vDis[i][1 << i] = 1;
		}
		for (int mask = 1; mask < m_iMaskCount; mask++)
		{
			for (int i = 0; i < m_c; i++)
			{
				if (vDis[i][mask] >= m_iNotMay)
				{
					continue;
				}
				for (int next = 0 ;next < m_c ;next++ )
				{
					if ((1 << next) & mask)
					{
						continue;//已經(jīng)訪問
					}
					const int iNewMask = (1 << next) | mask;
					vDis[next][iNewMask] = min(vDis[next][iNewMask], vDis[i][mask] + floyd.m_vMat[i][next]);
				}
			}
		}
		int iRet = m_iNotMay;
		for (const auto& v : vDis)
		{
			iRet = min(iRet, v.back());
		}
		return iRet-1;
	}
	const int m_iNotMay = 100'000;
	int m_c, m_iMaskCount;

};

2023年1月

class Solution {
public:
int shortestPathLength(vector<vector>& graph) {
auto Add = [this](int iMask, int iPos, int iOpeNum)
{
if (INT_MAX != m_vMaskPosMinOpe[iMask][iPos])
{
return;
}
m_vQue.emplace_back(iMask, iPos);
m_vMaskPosMinOpe[iMask][iPos] = iOpeNum;
};
m_c = graph.size();
for (int i = 0; i < sizeof(m_vMaskPosMinOpe) / sizeof(m_vMaskPosMinOpe[0]); i++)
{
for (int j = 0; j < sizeof(m_vMaskPosMinOpe[0]) / sizeof(m_vMaskPosMinOpe[0][0]); j++)
{
m_vMaskPosMinOpe[i][j] = INT_MAX;
}
}
for (int i = 0; i < m_c; i++)
{
Add(1 << i, i, 0);
}
for (int i = 0; i < m_vQue.size(); i++)
{
const int iMask = m_vQue[i].first;
const int iPos = m_vQue[i].second;
for (auto& next : graph[iPos])
{
int iNewMask = iMask | (1 << next);
Add(iNewMask, next, m_vMaskPosMinOpe[iMask][iPos] + 1);
}
}
int iMin = INT_MAX;
for (int i = 0; i < sizeof(m_vMaskPosMinOpe[0]) / sizeof(m_vMaskPosMinOpe[0][0]); i++)
{
iMin = min(iMin, m_vMaskPosMinOpe[(1 << m_c) - 1][i]);
}
return iMin;
}
vector<std::pair<int,int>> m_vQue;
int m_vMaskPosMinOpe[1 << 12 ][12];
int m_c;
};

2023年8月

class Solution {
public:
int shortestPathLength(vector<vector>& graph) {
auto Add = [this](int iMask, int iPos, int iOpeNum)
{
if (INT_MAX != m_vMaskPosMinOpe[iMask][iPos])
{
return;
}
m_vQue.emplace_back(iMask, iPos);
m_vMaskPosMinOpe[iMask][iPos] = iOpeNum;
};
m_c = graph.size();
for (int i = 0; i < sizeof(m_vMaskPosMinOpe) / sizeof(m_vMaskPosMinOpe[0]); i++)
{
for (int j = 0; j < sizeof(m_vMaskPosMinOpe[0]) / sizeof(m_vMaskPosMinOpe[0][0]); j++)
{
m_vMaskPosMinOpe[i][j] = INT_MAX;
}
}
for (int i = 0; i < m_c; i++)
{
Add(1 << i, i, 0);
}
for (int i = 0; i < m_vQue.size(); i++)
{
const int iMask = m_vQue[i].first;
const int iPos = m_vQue[i].second;
for (auto& next : graph[iPos])
{
int iNewMask = iMask | (1 << next);
Add(iNewMask, next, m_vMaskPosMinOpe[iMask][iPos] + 1);
}
}
int iMin = INT_MAX;
for (int i = 0; i < sizeof(m_vMaskPosMinOpe[0]) / sizeof(m_vMaskPosMinOpe[0][0]); i++)
{
iMin = min(iMin, m_vMaskPosMinOpe[(1 << m_c) - 1][i]);
}
return iMin;
}
vector<std::pair<int,int>> m_vQue;
int m_vMaskPosMinOpe[1 << 12 ][12];
int m_c;
};

【動態(tài)規(guī)劃】【廣度優(yōu)先搜索】【狀態(tài)壓縮】847 訪問所有節(jié)點的最短路徑,# 算法題,數(shù)據(jù)結構與算法,動態(tài)規(guī)劃,寬度優(yōu)先,c++,算法,LeetCode,圖論,狀態(tài)壓縮

擴展閱讀

視頻課程

有效學習:明確的目標 及時的反饋 拉伸區(qū)(難度合適),可以先學簡單的課程,請移步CSDN學院,聽白銀講師(也就是鄙人)的講解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成戰(zhàn)斗了,為老板分憂,請學習C#入職培訓、C++入職培訓等課程
https://edu.csdn.net/lecturer/6176

相關

下載

想高屋建瓴的學習算法,請下載《喜缺全書算法冊》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想對大家說的話
聞缺陷則喜是一個美好的愿望,早發(fā)現(xiàn)問題,早修改問題,給老板節(jié)約錢。
子墨子言之:事無終始,無務多業(yè)。也就是我們常說的專業(yè)的人做專業(yè)的事。
如果程序是一條龍,那算法就是他的是睛

測試環(huán)境

操作系統(tǒng):win7 開發(fā)環(huán)境: VS2019 C++17
或者 操作系統(tǒng):win10 開發(fā)環(huán)境: VS2022 C++17
如無特殊說明,本算法用**C++**實現(xiàn)。

【動態(tài)規(guī)劃】【廣度優(yōu)先搜索】【狀態(tài)壓縮】847 訪問所有節(jié)點的最短路徑,# 算法題,數(shù)據(jù)結構與算法,動態(tài)規(guī)劃,寬度優(yōu)先,c++,算法,LeetCode,圖論,狀態(tài)壓縮文章來源地址http://www.zghlxwxcb.cn/news/detail-817359.html

到了這里,關于【動態(tài)規(guī)劃】【廣度優(yōu)先搜索】【狀態(tài)壓縮】847 訪問所有節(jié)點的最短路徑的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【動態(tài)規(guī)劃】【廣度優(yōu)先】LeetCode2258:逃離火災

    【動態(tài)規(guī)劃】【廣度優(yōu)先】LeetCode2258:逃離火災

    視頻算法專題 二分查找算法合集 動態(tài)規(guī)劃匯總 二分查找 給你一個下標從 0 開始大小為 m x n 的二維整數(shù)數(shù)組 grid ,它表示一個網(wǎng)格圖。每個格子為下面 3 個值之一: 0 表示草地。 1 表示著火的格子。 2 表示一座墻,你跟火都不能通過這個格子。 一開始你在最左上角的格子

    2024年02月05日
    瀏覽(20)
  • AcWing算法學習筆記:動態(tài)規(guī)劃(背包 + 線性dp + 區(qū)間dp + 計數(shù)dp + 狀態(tài)壓縮dp + 樹形dp + 記憶化搜索)

    AcWing算法學習筆記:動態(tài)規(guī)劃(背包 + 線性dp + 區(qū)間dp + 計數(shù)dp + 狀態(tài)壓縮dp + 樹形dp + 記憶化搜索)

    算法 復雜度 時間復雜度0(nm) 空間復雜度0(nv) 代碼 算法 通過滾動數(shù)組對01背包樸素版進行空間上的優(yōu)化 f[i] 與 f[i - 1]輪流交替 若體積從小到大進行遍歷,當更新f[i, j]時,f[i - 1, j - vi] 已經(jīng)在更新f[i, j - vi]時被更新了 因此體積需要從大到小進行遍歷,當更新f[i, j]時,f[i - 1,

    2024年02月21日
    瀏覽(21)
  • 【BFS三維路徑規(guī)劃】廣度優(yōu)先搜索算法無人機三維路徑規(guī)劃【含Matlab源碼 270期】

    【BFS三維路徑規(guī)劃】廣度優(yōu)先搜索算法無人機三維路徑規(guī)劃【含Matlab源碼 270期】

    獲取代碼方式1: 完整代碼已上傳我的資源:【三維路徑規(guī)劃】基于matlab廣度優(yōu)先搜索算法無人機三維路徑規(guī)劃【含Matlab源碼 270期】 獲取代碼方式2: 付費專欄Matlab路徑規(guī)劃(初級版) 備注: 點擊上面藍色字體付費專欄Matlab路徑規(guī)劃(初級版),掃描上面二維碼,付費29.9元

    2024年02月02日
    瀏覽(34)
  • 藍橋杯-回路計數(shù)(狀態(tài)壓縮、動態(tài)規(guī)劃)

    藍橋學院由 21 21 21 棟教學樓組成,教學樓編號 11 11 11 ?? 到 21 21 21 ??。對于兩棟教學樓 a a a 和 b b b ?,當 a a a 和 b b b 互質時, a a a 和 b b b 之間有一條走廊直接相連,兩個方向皆可通行,否則沒有直接連接的走廊。 小藍現(xiàn)在在第一棟教學樓,他想要訪問每棟教學樓正

    2024年02月08日
    瀏覽(32)
  • 深度優(yōu)先搜索與動態(tài)規(guī)劃|543, 124, 687

    深度優(yōu)先搜索與動態(tài)規(guī)劃|543, 124, 687

    好久沒寫二叉樹了,主要還是看遍歷的順序是什么樣的。 這個有點繞不出來。繞一遍, root -10 進去,root.left是root 9,root.right是root 20 root 9 進去得到的return是9,res更新得到9 root 20進去,root.left是root 15,root.right是root 7 root 15進去得到的return是15,res更新得到15 root 7進去得到的

    2024年02月13日
    瀏覽(21)
  • [動態(tài)規(guī)劃,二進制狀態(tài)壓縮] 旅行商問題

    題目描述 一個國家有 n 個城市,每兩個城市之間都開設有航班,從城市 i 到城市 j 的航班價格為 cost[i, j] ,而且往、返航班的價格相同。 售貨商要從一個城市出發(fā),途徑每個城市 1 次(且每個城市只能經(jīng)過 1 次),最終返回出發(fā)地,而且他的交通工具只有航班,請求出他旅

    2024年01月24日
    瀏覽(21)
  • 【狀態(tài)壓縮】【動態(tài)規(guī)劃】【C++算法】691貼紙拼詞

    【狀態(tài)壓縮】【動態(tài)規(guī)劃】【C++算法】691貼紙拼詞

    視頻算法專題 動態(tài)規(guī)劃匯總 狀態(tài)壓縮 我們有 n 種不同的貼紙。每個貼紙上都有一個小寫的英文單詞。 您想要拼寫出給定的字符串 target ,方法是從收集的貼紙中切割單個字母并重新排列它們。如果你愿意,你可以多次使用每個貼紙,每個貼紙的數(shù)量是無限的。 返回你需要拼

    2024年01月19日
    瀏覽(28)
  • C++ 動態(tài)規(guī)劃 狀態(tài)壓縮DP 最短Hamilton路徑

    C++ 動態(tài)規(guī)劃 狀態(tài)壓縮DP 最短Hamilton路徑

    給定一張 n 個點的帶權無向圖,點從 0~n?1 標號,求起點 0 到終點 n?1 的最短 Hamilton 路徑。 Hamilton 路徑的定義是從 0 到 n?1 不重不漏地經(jīng)過每個點恰好一次。 輸入格式 第一行輸入整數(shù) n 。 接下來 n 行每行 n 個整數(shù),其中第 i 行第 j 個整數(shù)表示點 i 到 j 的距離(記為 a[

    2024年02月19日
    瀏覽(24)
  • 【圖論--搜索篇】寬度優(yōu)先搜索,廣度優(yōu)先搜索

    【圖論--搜索篇】寬度優(yōu)先搜索,廣度優(yōu)先搜索

    今日語錄: 成功是一種心態(tài),如果你相信自己能做到,那你已經(jīng)邁出成功的第一步。

    2024年01月24日
    瀏覽(26)
  • 快來看看萌新小白學習動態(tài)規(guī)劃、深度優(yōu)先搜索、貪心

    快來看看萌新小白學習動態(tài)規(guī)劃、深度優(yōu)先搜索、貪心

    由于比賽臨近,老師給我們布置了一些LeetCode算法題目,但是我在學完Hello算法的數(shù)據(jù)結構部分之后,就跑去學習算法第四版了。被一些安全比賽耽誤,算法的學習進度比較慢,通過這篇文章就可以體現(xiàn)出我的技術還是比較菜的,還望諒解,哈哈。 LeetCode題目#206 反轉鏈表 這是

    2024年04月14日
    瀏覽(39)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包