LeetCode 1066. Campus Bikes II


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

https://leetcode.com/problems/campus-bikes-ii/discuss/320683/Java-7ms-DFS-+-Memorization-Solution-Beats-97


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM