今天开始定期记录本人在leetcode上刷题时遇到的有意思的题目。
 

517. Super Washing Machines
 
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 the minimum 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.

乍看此题,我们可能会想到是否能用DP求解,毕竟像求最值这类问题,是很容易与DP联系在一起的。事实也正是如此。
第一步,我们判断所有的machines能不能被成功地分配到m个相同的组。这很容易判断,在此不赘述。这步做完,我们可以得到每堆machine的最终数量(假如能被成功分配为m个相同的组),记为n。
接下来,我们看一下如何将这个问题分解为子问题,从而易于用DP求解。我们从数组的第一个元素开始看。
第一种情况,该元素=n。这表明第一堆已经不需要再做任何移动。我们仅需求出对剩余的数组(从第二个开始到末尾)的解,该子数组的解就是我们整个问题的解。
第二种情况,该元素>n。这种情况说明,我们需要从第一堆中取出足够的machine,将它移动到相邻的第二堆,将移动的数量记为n1. 然后,再对剩余的子数组递归求解,假设得到的解为n2.这时我们观察题干,不同堆中的移动是独立的。比如堆1移动1个machine到堆2,堆2移动1一个machine到堆3。。。这个移动序列只被记为一次。有这个结论,我们回到第二种情况,n1和n2也是独立的。所以这种情况下我们的解是max(n1,n2)。
第三种情况,该元素<n。这种情况,我们需要从第二堆中取出足够的machine,将它移动到第一堆。如果第二堆的数量仍然不够呢?那就从第三堆取,以此类推。我们可以用一个例子来说明。
 
0,1,3,14,2
 
这个例子最终每堆的数量应该是4.然而第一堆=0,那么我们需要从第二堆中取4个machine(n1),然而第二堆的数量是1,还是不够。且第二堆自己最终数量也必须是4,那么它总共需要从第三堆取7个(n2)。以此类推,第三堆需要从第四堆取8个(n3),才能满足左边所有堆的需求。到第四堆,我们发现,它的数量足够了,不必再向它的右边再取machine了。于是我们可以通过一个循环计算出所需要移动的数量nx = max(n1,n2...)。然后再递归求解剩余子数组形成的子问题,解记为ny。对于本例来说,这个子问题就是对数组第四个元素开始的子数组求出的解。看到这里,也许我们的解可以呼之欲出了,就是max(nx,ny)?
然而,事实并非如此。再次阅读题干,不同的堆上的操作,确实是独立的。但是对同一堆,情况并非如此。还是观察之前的例子,第四堆需要移动8个元素到第三堆,它还需要移动2个元素到右边的第五堆。所以整个问题的解是8+2=10堆,而不是max(8,2)的8堆,原因就在于对同一堆上的操作,没有独立性。所以我们在设计递归函数的时候,除了返回整个操作的最小move数,还必须返回边界元素的move数,从而便于子问题返回时,计算主问题的解。
 
贴上代码:
int findMinMoves(vector<int>& machines) {
if (machines.empty()) return ;
int sum = accumulate(begin(machines), end(machines), );
if (sum % machines.size() == ) {
int target = sum / machines.size();
return findMinMoves(machines, , target).first;
}
else return -;
} // 返回pair<minMove, boundaryMove>
// boundaryMove表示从start位置和start+1位置之间发生move的数量(双向)
pair<int, int> findMinMoves(vector<int>& machines, int start, int target) {
if (start == machines.size() - ) {
return make_pair(, );
}
if (target <= machines[start]) {
int move = machines[start] - target;
machines[start + ] += move;
int minMove = findMinMoves(machines, start + , target).first;
return make_pair(max(move, minMove), move);
}
else {
int i = start;
int maxMove = ;
int move;
do {
move = target - machines[i];
maxMove = max(maxMove, move);
machines[i + ] -= move;
i++;
} while (machines[i] < target);
pair<int, int> rem = findMinMoves(machines, i, target);
int rMove = rem.first;
maxMove = max(maxMove, rMove);
maxMove = max(maxMove, move + rem.second);
return make_pair(maxMove, target - machines[i]);
}
}

Leetcode - 517 Super Washing Machines的更多相关文章

  1. 第十五周 Leetcode 517. Super Washing Machines(HARD) 贪心

    Leetcode517 很有趣的一道题 由于每一步可以任选某些数字对它们进行转移,所以实际上是在求最优解中的最复杂转移数. 那么我们考虑,到底哪一个位置要经过的流量最大呢? 枚举每个位置,考虑它左边的 ...

  2. 517 Super Washing Machines 超级洗衣机

    详见:https://leetcode.com/problems/super-washing-machines/description/ C++: class Solution { public: i ...

  3. 517. Super Washing Machines

    ▶ 超级洗碗机.给定一个有 n 元素的整数数组,我们把 “将指定位置上元素的值减 1,同时其左侧或者右侧相邻元素的值加 1” 称为一次操作,每个回合内,可以选定任意 1 至 n 个位置进行独立的操作, ...

  4. [LeetCode] Super Washing Machines 超级洗衣机

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

  5. [Swift]LeetCode517. 超级洗衣机 | Super Washing Machines

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

  6. LeetCode517. Super Washing Machines

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

  7. [LeetCode] 313. Super Ugly Number 超级丑陋数

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  8. Java实现 LeetCode 517 超级洗衣机

    517. 超级洗衣机 假设有 n 台超级洗衣机放在同一排上.开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的. 在每一步操作中,你可以选择任意 m (1 ≤ m ≤ n) 台洗衣机,与此同时将 ...

  9. Leetcode 313. super ugly number

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

随机推荐

  1. sql获取时间段内的所有日期

    ,'2015-01-01 00:00:00') h INTO vinson_h DELETE vinson_h DECLARE @h int SELECT @h=DATEDIFF(HOUR,'2015 ...

  2. js将一维数组转化为二维数组

    遇到的问题: 后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上. 例:[1,2,3,4,5,6,7,8,9,10] ...

  3. 分布式一致性算法2PC和3PC

    为了解决分布式一致性问题,产生了不少经典的分布式一致性算法,本文将介绍其中的2PC和3PC.2PC即Two-Phase Commit,译为二阶段提交协议.3PC即Three-Phase Commit, ...

  4. python3下GUI界面设计之控件精确定位

    #codeing:utf-8import tkinterimport tkinter.messageboxfrom tkinter import filedialogfrom tkinter impo ...

  5. 啊哈算法第四章第三节 层层递进-广度优先搜索 java实现

    package corejava; public class FourThree { static int [][]a=new int[50][50]; static int [][]b=new in ...

  6. Django 命令

    django #安装: pip3 install django 添加环境变量 #1 创建project django-admin startproject mysite ---mysite ---se ...

  7. ajax的4个字母分别是什么意思

    Asynchronous JavaScript and XML 的缩写,异步的JavaScript和XML.在不重新加载整个页面的情况下 ,AJAX 与服务器交换数据并更新部分网页.

  8. Java好的的工具类:JsonUtils

    package com.nxhfzx.gdshopping.utils; import java.util.List; import com.fasterxml.jackson.core.JsonPr ...

  9. Rocket MQ 2 - Namesrv

    通过上文中使用可以看到,主要逻辑还是在NamesrvController中包含KVConfigManager负责配置相关的读写,RouteInfoManager负责路由信息的管理; 启动定时任务定时打 ...

  10. 基于Ubuntu系统XAMPP环境安装以及DVWA渗透测试系统安装(详解的不能再详解了)

    首先这是X勺年人生第二次博,用来记录一下转折于我而言.做个简介,这个Ubuntu是linux的一种吧,然 然后这个Ubuntu是我刚简单安装(在虚拟机上)没有经过任何配置,从头开始,我这绝壁的小白,其 ...