Backtracing + Pruning (TLE)
最容易的解法是 backtracing,但是即使加了剪枝,還是會超時。
class Solution { public: int min_dist=INT_MAX; int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) { vector<bool> bikeUsed(bikes.size(),false); dfs(workers,bikes,0,bikeUsed,0); return min_dist; } // assign a bike to employee i void dfs(vector<vector<int>>& workers, vector<vector<int>>& bikes, int i, vector<bool> &bikeUsed, int sum){ if (i==workers.size()){ min_dist = min(min_dist, sum); return; } if (sum>min_dist) return; // pruning for (int j=0;j<bikes.size();++j){ if (bikeUsed[j]) continue; bikeUsed[j] = true; dfs(workers,bikes,i+1,bikeUsed,sum+dist(workers[i],bikes[j])); bikeUsed[j] = false; } } int dist(vector<int> worker, vector<int> bike){ return abs(worker[0]-bike[0])+abs(worker[1]-bike[1]); } };
Backtracing + Memoization
加一個memo減少遞歸次數。由於上面的寫法的遞歸函數返回void,要修改為有返回值的寫法才能運用memo。
讓 dfs 返回值為最小的距離和,然后將 bikeUsed 作為判斷標識。由於bike的數量<=10,我們可以用int二進制對這個vector進行壓縮作為key。這里只需要 bikeUsed 的原因是,從這個數組我們能得知分配了多少車,而人又是根據序號依次分配的,所以能得出哪些人還沒有車。所以 bikeUsed 數組就能唯一確定一個子問題的狀態。
class Solution { public: int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) { vector<bool> bikeUsed(bikes.size(),false); unordered_map<int,int> memo; return dfs(workers,bikes,0,bikeUsed,memo); } // assign a bike to employee i int dfs(vector<vector<int>>& workers, vector<vector<int>>& bikes, int i, vector<bool> &bikeUsed, unordered_map<int,int> &memo){ if (i==workers.size()) return 0; int compressed_bikeUsed=compress(bikeUsed); if (memo.count(compressed_bikeUsed)) return memo[compressed_bikeUsed]; int min_dist=INT_MAX; for (int j=0;j<bikes.size();++j){ if (bikeUsed[j]) continue; bikeUsed[j] = true; min_dist = min(min_dist, dfs(workers,bikes,i+1,bikeUsed,memo) + dist(workers[i],bikes[j])); bikeUsed[j] = false; } return memo[compressed_bikeUsed]=min_dist; } int dist(vector<int> worker, vector<int> bike){ return abs(worker[0]-bike[0])+abs(worker[1]-bike[1]); } int compress(vector<bool> bikeUsed){ int res=0; for (int i=0;i<bikeUsed.size();++i){ res <<= 1; res |= bikeUsed[i]; } return res; } };
DP
既然可以 Backtracing + Memoization,那么也肯定可以 dp 來做。面試中遇到還是 backtracing 不容易出錯。
待補...
https://leetcode.com/problems/campus-bikes-ii/discuss/305218/DFS-+-Pruning-And-DP-Solution
Reference
https://leetcode.com/problems/campus-bikes-ii/discuss/305218/DFS-+-Pruning-And-DP-Solution