[朝花夕拾] LeetCode刷題合輯

20220228 1601. 最多可達成的換樓請求數目

題目鏈接:https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests/

方法一:DFS 枚舉

枚舉所有換樓請求的選擇與不選擇兩種情況,最後判斷是否滿足題意,時間複雜度爲 O(2 ^ m),m 爲請求個數,依題意 m <= 16,符合要求。

 1 #include <cstring> 
 2 
 3 const int N = 25;
 4 
 5 class Solution {
 6 public:
 7     int a[N][N], b[N];
 8     int dfs(int o, int x, int n, int m) {
 9         int res = 0;
10         if (o == m) {
11             int tot = 0;
12             for (int i = 0; i < n; i++) {
13                 for (int j = 0; j < m; j++)
14                     tot += (b[j] ? a[j][i] : 0);
15                 if (tot != 0) return 0;
16             }
17             return x;        
18         }
19         b[o] = 1;
20         res = dfs(o + 1, x + 1, n, m);
21         b[o] = 0;
22         res = max(res, dfs(o + 1, x, n, m));
23         return res;
24     }
25     int maximumRequests(int n, vector<vector<int>>& requests) {
26         int m = requests.size();
27         for (int i = 0; i < m; i++)
28             a[i][requests[i][0]] += -1, a[i][requests[i][1]] += 1;
29         memset(b, 0, sizeof(b));
30         return dfs(0, 0, n, m); 
31     }
32 };

其實不用轉換爲二維數組,可以節省空間,並且 DFS 過程中就可以維護是否滿足條件而不需要最後用 for 循環判斷,代碼有優化空間。

方法二:二進制位運算枚舉

由於對於請求只有選擇與不選擇兩種可能,使用二進制位運算,會大幅精簡代碼,但需要再最後用 for 循環判斷是否滿足條件,故時間複雜度會達到 O(n * 2 ^ m)。

 1 const int N = 25;
 2 
 3 class Solution {
 4 public:
 5     int maximumRequests(int n, vector<vector<int>>& r) {
 6         int a[N], m = r.size(), ans = 0;
 7         for (int o = 0; o < (1 << m); o++) {
 8             memset(a, 0, sizeof(a));
 9             int res = 0;
10             for (int i = 0; i < m; i++)
11                 if (o & (1 << i))
12                     a[r[i][0]]--, a[r[i][1]]++, res++;
13             int tot = 0;
14             for (int i = 0; i < n; i++)
15                 tot += (a[i] == 0);
16             if (tot == n) ans = max(res, ans);
17         }
18         return ans;
19     }
20 };

其他:最小費用最大流

由於數據量並不大,用網絡流有點殺雞用牛刀了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章