概率dp|math
lc365
法1. bool dfs(0,0)六种情况讨论
法2. 状态机写法
class Solution
{
int target;
int cx, cy;
// 记录已经遍历过的状态,避免重复计算
unordered_set<long long> visited;
public:
bool canMeasureWater(int x, int y, int targetCapacity) {
this->cx = x;
this->cy = y;
this->target = targetCapacity;
if (target == 0) return true;
if (x + y < target) return false;
return dfs(0, 0);
}
bool dfs(int x, int y)
{
// 状态标记:将 (x, y) 转换为唯一的 long long 值,方便存入 visited
long long state = (long long)x * (cy + 1) + y;
if (visited.count(state))
{
return false; //memo
}
visited.insert(state);
if (x == target || y == target || x + y == target) {
return true;
}
// 尝试所有可能的操作:
// 1. 装满第一个水壶(容量为 cx)
if (dfs(cx, y)) return true;
// 2. 装满第二个水壶(容量为 cy)
if (dfs(x, cy)) return true;
// 3. 清空第一个水壶
if (dfs(0, y)) return true;
// 4. 清空第二个水壶
if (dfs(x, 0)) return true;
// 5. 从第一个水壶倒到第二个水壶,直到第二个满或第一个空
int pour1to2 = min(x, cy - y);
if (dfs(x - pour1to2, y + pour1to2)) return true;
// 6. 从第二个水壶倒到第一个水壶,直到第一个满或第二个空
int pour2to1 = min(y, cx - x);
if (dfs(x + pour2to1, y - pour2to1)) return true;
return false;
}
};
状态机模型
class Solution {
public:
bool canMeasureWater(int x, int y, int target) {
if (target == 0) return true;
if (x + y < target) return false;
if (x > y) swap(x, y);
using State = pair<int, int>;
unordered_map<State, bool> memo;
function<bool(int, int)> dfs = [&](int a, int b) -> bool {
State state = {a, b};
if (memo.count(state))
return memo[state];
if (a == target || b == target || a + b == target) {
return memo[state] = true;
}
vector<pair<int, int>> ops =
{
{x, b}, {a, y},
{0, b}, {a, 0},
{max(0, a - (y - b)), min(y, b + a)},
{min(x, a + b), max(0, b - (x - a))}
};
for (auto& [na, nb] : ops)
{
if (dfs(na, nb)) {
return memo[state] = true;
}
}
return memo[state] = false;
};
return dfs(0, 0);
}
};
lc837 概率dp
class Solution {
public:
double new21Game(int N, int K, int W) {
double dp[K+W];
double s=0;
for(int i = K; i<K+W; ++i)
{
dp[i] = i<=N? 1:0;
s+=dp[i];
}
for(int i = K-1; i>=0; --i)
{
dp[i] = s/W;
s-=(dp[i+W]-dp[i]);
}
return dp[0];
}
};