iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0

今天要寫的是狀態壓縮
DP在記錄狀態的時候有許多不同的方式,如果要記錄的狀態太多,或需要使用的維度太高,就會考慮使用狀態壓縮。
直接用例題來解釋:

例題&解釋

訪問所有節點的最短路徑
題目敘述:給定一張無向圖,返回任意選擇一起點,訪問完所有節點的最短路徑長(可用相同的邊)((也就是可以走回重複的點))
思路:
題目本身的問題並不複雜,就是選一個起點,從起點找完所有的節點,紀錄最短的路徑長,返回答案就好,思路本身也很簡單,就是暴力法,把每一個種組合都找一次,問題只是實現,既然路徑可以返回,就不能單純只是記錄每一個節點的訪問或未被訪問,這時候就需要狀態壓縮。
題目中,節點數量N小於12,所以可以用這種方式紀錄:
vis{start}{mask}
start代表起始節點,mask代表訪問的狀態

MASK表示訪問狀態

要只用一個維度表示N個節點的訪問狀態,就是狀態壓縮的精髓,其實就是用位元來記錄
ex. 00010可以代表從1號節點出發,還沒訪問過其他節點
00011可以代表1,2號節點都被訪問過了

程式碼實現

有了這種紀錄方式之後,就對每一個起點BFS就好,只要遇到有0111⋯⋯11這種狀態(全部訪問完成)就返回答案

class Solution {
public:
    int shortestPathLength(vector<vector<int>>& graph) {
        int n = graph.size();

        queue< tuple<int, int, int> > q;
        vector<vector<bool>> vis(n, vector<bool>(1 << n));
        for(int i = 0; i < n; i++) {
            q.push({i, 1 << i, 0});
            vis[i][1 << i] = true;
        }
        while(!q.empty()) {
            auto [cur, mask, dist] = q.front();
            q.pop();

            if(mask == (1 << n) - 1) return dist;

            for(int x : graph[cur]) {
                int nextmask = mask | (1 << x);
                if(!vis[x][nextmask]) {
                    q.push({x, nextmask, dist + 1});
                    vis[x][nextmask] = true;
                }
            }
        }
        return 0;
        }
};

上一篇
DAY19-動態規劃(二)
下一篇
DAY21-動態規劃(四)
系列文
算法與數據結構&力扣例題實戰22
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言