题目描述
有两个水壶,容量分别为 x 和 y 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 target 升。
如果可以得到 target 升水,最后请用以上水壶中的一或两个来盛放取得的 target 升水。
你可以:
- 装满任意一个水壶;
- 清空任意一个水壶;
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空;
示例:
输入: jug1Capacity = 3, jug2Capacity = 5, targetCapacity = 4
输出: true
解题思路
说是深度优先其实感觉有回溯的味道,简单来说,每次行动也就这么有限个操作,暴力遍历所有排列组合,遇到满足条件的立即返回。
考虑递归函数的返回值与形参。根据题目要求返回类型,递归返回类型取bool,每层递归都需要借助上层递归的状态值,故形参有remain_x, remain_y表示x, y壶当前存量。
返回条件。满足合法条件即返回,x壶或y壶装target,抑或x、y壶之和装够target。为防止状态成环进而陷入死循环,考虑visited[][]数组防止重复访问。因此,递归形参也需添加visited[][]。
单层逻辑。递归所有操作状态,只要有一个为真即可返回,故用||连接各子递归函数。考虑可操作的状态:
- 装满
x,即(x, remain_y); - 装满
y,即(remain_x, y); - 清空
x,即(0, remain_y); - 清空
x,即(remain_x, 0); - 用
x装满y,即(remain_x - min(y - remain_y, remain_x), remain_y + min(y - remain_y, remain_x)); - 用
y装满x,即(remain_x + min(x - remain_x, remain_y), remain_y - min(x - remain_x, remain_y));
深度优先,递归实现:
class Solution {
int x, y, target;
public:
bool canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {
x = jug1Capacity;
y = jug2Capacity;
target = targetCapacity;
vector<vector<bool>> visited(x + 1, vector<bool>(y + 1));
return dfs(0, 0, visited);
}
bool dfs(int remain_x, int remain_y, vector<vector<bool>>& visited){
if(visited[remain_x][remain_y]) return false;
if(remain_x == target || remain_y == target || remain_x + remain_y == target) return true;
visited[remain_x][remain_y] = true;
return dfs(0, remain_y, visited) || dfs(remain_x, 0, visited) || dfs(x, remain_y, visited) || dfs(remain_x, y, visited) || dfs(remain_x - min(remain_x, y - remain_y), remain_y + min(remain_x, y - remain_y), visited) ||

本文介绍了如何使用深度优先搜索和回溯算法解决水壶问题,即两个不同容量的水壶如何通过倒水操作得到特定容量的目标水量。通过递归和状态记录避免重复计算,同时探讨了使用哈希集合优化空间复杂度的方法,包括函数指针和函数对象。此外,还提出了裴蜀定理的数学解决方案,简化了问题的求解过程。
最低0.47元/天 解锁文章
378

被折叠的 条评论
为什么被折叠?



