牛客题单__动态规划课程概率dp例题
文章目录
NC15532 Happy Running
大意:
问围着一个x的跑道跑顺时针跑,打卡完毕的时候跑k米及以上的概率。两个打卡点是随机的,必须先打第一个再打第二个,如果先跑到第二个,那么也要先打完第一个点然后再绕一圈到第二个点打卡
思路:
当k<=x时,如果两个点都在前k米,并且第一个点在第二个点前面,那么不行
所以概率为0.5+0.5 * (1-两个都在前k米的概率)
当k大于2x时,必然跑不到
介于x到2x之间时,需要第2个点在第1个点前面,同时两个点都不能在前(2*k-x)米
#include <bits/stdc++.h>
using namespace std;
int t;
double k, x;
int main(void) {
cin >> t;
while (t--) {
cin >> k >> x;
double res = 0;
if (k <= x) {
res = 0.5;
res += 1.0 * (1.0 * (x - k) / x) * (1.0 * (k + x) / 2 / x);
} else if (k <= 2 * x) {
res += 1.0 * (1.0 * (2 * x - k) / x) * (1.0 * (2 * x - k) / 2 / x);
}
printf("%.2lf\n", res);
}
return 0;
}
POJ2096 Collecting Bugs
大意:
现在有很多bug,按照位置分可以分为n类,按照类型分可以分为m类,现在有一个人,每天可以找到一个bug,问找到全部n个位置m个类型至少各有一个bug,花费天数的期望
思路:

但是 f [ i ] [ j ] f[i][j] f[i][j]等式右边也有 f [ i ] [ j ] f[i][j] f[i][j],不好转移,所以将其移项到左边,化简一下即可转移了
写的时候大爆搜即可
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
using namespace std;
const int N = 1e3 + 5;
typedef long long LL;
double f[N][N];
int n, m;
double dp(int x, int y) {
if (f[x][y] != 0) return f[x][y];
if (x == n && y == m) return 0;
if (x > n || y > m) return 0;
double p1 = ((1.0 * x / n )* (1.0 * y / m));
double p2 = ((1.0 * x / n )* (1.0 - 1.0 * y / m));
double p3 = ((1.0 - 1.0 * x / n) * 1.0 * y / m);
double p4 = ((1.0 - 1.0 * x / n) * (1.0 - 1.0 * y / m));
return f[x][y] = (p1 + p2 * (dp(x, y + 1) + 1.0) + p3 * (dp(x + 1, y) + 1.0) +
p4 * (dp(x + 1, y + 1) + 1.0)) /
(1.0 - p1);
}