1. 程式人生 > >演算法練習筆記(十二)—— 超級洗衣機

演算法練習筆記(十二)—— 超級洗衣機

https://leetcode.com/problems/super-washing-machines/#/description

You have n super washing machines on a line. Initially, each washing machine has some dresses or is empty.

For each move, you could choose any m (1 ≤ m ≤ n) washing machines, and pass one dress of each washing machine to one of its adjacent washing machines at the same time 

.

Given an integer array representing the number of dresses in each washing machine from left to right on the line, you should find theminimum number of moves to make all the washing machines have the same number of dresses. If it is not possible to do it, return -1.

Example1

Input: [1,0,5]

Output:
3 Explanation: 1st move: 1 0 <-- 5 => 1 1 4 2nd move: 1 <-- 1 <-- 4 => 2 1 3 3rd move: 2 1 <-- 3 => 2 2 2

Example2

Input: [0,3,0]

Output: 2

Explanation: 
1st move:    0 <-- 3     0    =>    1     2     0    
2nd move:    1     2 --> 0    =>    1     1     1     

Example3

Input: [0,2,0]

Output: -1

Explanation: 
It's impossible to make all the three washing machines have the same number of dresses. 

Note:

  1. The range of n is [1, 10000].
  2. The range of dresses number in a super washing machine is [0, 1e5].
假設有n臺洗衣機,每個洗衣機裡的衣服數量都非負(廢話= =),現在要移動衣服使每臺洗衣機中的衣服數量一樣,每一次能夠同時移動不同洗衣機的一件衣服,求使衣服移動的最小步數 解答思考: 在剛開始,原諒我沒有看到同時這個詞,於是悲劇就發生了,我得出了不同時的動態規劃解答,然而與同時的要求不符 我是從最後開始往前遍歷洗衣機,然後每一次,都使最後一個洗衣機裡的衣服數通過最小步數移動變為所需數量,然後將這一個洗衣機扔出容器,進行下一步,有一點貪心演算法的感覺 為了慰藉我努力的心靈,我還是要把自己的錯誤解答放上來 (若不同時)
class Solution {
public:
    int findMinMoves(vector<int>& machines) {
        int size = machines.size();
        int count = 0;
        for(int i = 0; i < size; i++){
            count += machines[i];
        }
        if(count%size != 0)return -1;
        else
        return MinMoves(machines, count / size);
    }
    
    int MinMoves(vector<int>& mac, int key){
        int move = 0;
        int size = mac.size();
        if(size == 1)return 0;
        if(mac[size - 1] == key);
        else if(mac[size - 1] > key){
            move = mac[size - 1] - key;
            mac[size - 2] += move;
        }
        else if(mac[size - 1] < key){
            int nums = key - mac[size - 1];
            for(int i = size - 2; i >= 0; i --){
                if(mac[i] > 0 && mac[i] < nums){
                    move += mac[i] * (size - 1 - i);
                    nums -= mac[i];
                    mac[i] = 0;
                }
                else if(mac[i] > 0 && mac[i] >= nums){
                    move += nums * (size - 1 - i);
                    mac[i] -= nums;
                    break;
                }
            }
        }
        mac.pop_back();
        return move + MinMoves(mac, key);
    }

};

然後說到正確解答,我參考了dalao的解答,而且只用了八行! 在這個解答中,主要便是對本次情景做出分析,並擬出一個平衡參量來解決了同時的問題,由於在每個洗衣機中,所缺數量的衣服和多出來的衣服,都是要被移動的,因此設定一個總體的平衡量,對每個洗衣機內需要被移動的衣服進行計數,同時通過加和解決可以同時移動兩件衣服的問題,如下所示:
int findMinMoves(vector<int>& machines) {
    int totalDresses = 0, size = machines.size();
    for (auto i = 0; i < size; ++i) totalDresses += machines[i];
    if (totalDresses % size != 0) return -1;
    
    auto targetDresses = totalDresses / size, totalMoves = 0, ballance = 0;
    for (auto i = 0; i < size; ++i) {
        ballance += machines[i] - targetDresses;
        totalMoves = max(totalMoves, max(machines[i] - targetDresses, abs(ballance)));
    }
    return totalMoves;
}