Codeforces 598D Igor In the Museum(概率DP)
来源:互联网 发布:ncs刷机软件 编辑:程序博客网 时间:2024/04/27 15:38
@(K ACMer)
题意:
在x轴上有n颗高度为h的树,现在你将有12 的概率,砍最左边的树,同样的概率砍最右边的树.然后对于每个树它有p 的概率会向左边倒,(1−p) 的概率会向右边倒.值得注意的是树的倒会引起类似多米诺骨牌效应,也就是如果一个树和它相邻的树和它的距离小于h,它往这颗树倒的时候,该树也会向同样的方向倒.为你这些树全部倒下的期望覆盖地面长度是多少?
分析:
开始很很容易想到一个记忆化搜索的思路,定义dfs(l,r,lf,rf) 为当前的最左边界的下标为l 最右边界下标为r ,最靠近l 的覆盖到了lf ,最靠近r 的覆盖到了rf .这样再分为:1.左边的树向左边倒,2.左边的树向右边倒,3.右边的树向左边倒,4.右边的树向右边倒四种情况来转移就可.
但是写出来记忆优化的时候发现lf 和rf 都太大了,必须需要用map来离散化,所以记忆化的数组是map<pair<int,int>,double>dp[l][r] 这样凭空多了个O(logn) 的复杂度,既超时间也超内存.
最后发现其实没有必要记录lf ,和rf 这样大的数只需要记录当前l 左边的树是向左倒还是向右倒,当前r 右边的树是向左倒还是向右倒,就可以推算出来lf 和rf .这是有状态dp[l][r][2][2]
code:
#include <iostream>#include <cstdio>#include <cstring>#include <set>#include <map>#include <stack>#include <vector>#include <string>#include <queue>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;typedef pair<int, int> pii;typedef long long ull;typedef long long ll;typedef vector<int> vi;#define xx first#define yy second#define rep(i, a, n) for (int i = a; i < n; i++)#define sa(n) scanf("%d", &(n))#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)const int mod = int(1e4) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;int n, h, v[2009];double p, eps = 1e-11;double dp[2009][2009][2][2];double dfs(int l, int r, int lf, int rf){ if (l > r) return 0; int li = l, ri =r; if (dp[li][ri][lf][rf]) return dp[li][ri][lf][rf]; int lff = l > 0 ? (lf == 0 ? v[l - 1] : v[l - 1] + h ) : -INF; int rff = r < n - 1 ? (rf == 1 ? v[r + 1] : v[r + 1] - h) : INF; double ret = 0.0; ret += p * 0.5 * (min(h, v[l] - lff) + dfs(l + 1, r, 0, rf)); int x = l + 1; while (x <= r && v[x] < v[x - 1] + h) x++; x--; ret += (1 - p) * 0.5 * (min(v[x] - v[l] + h, rff - v[l]) + dfs(x + 1, r, 1, rf)); ret += (1 - p) * 0.5 * (min(h, rff - v[r]) + dfs(l, r - 1, lf, 1)); x = r - 1; while (x >= l && v[x + 1] < v[x] + h) x--; x++; ret += p * 0.5 * (min(v[r] - v[x] + h, v[r] - lff) + dfs(l, x - 1, lf, 0)); return dp[li][ri][lf][rf] = ret + eps; //return dp[li][ri][make_pair(lf, rf)] = ret + eps;}int main(void){ sa(n), sa(h); cin >> p; rep (i, 0, n) sa(v[i]); sort(v, v + n); printf("%.15f\n", dfs(0, n - 1, 0, 0)); return 0;}
1 0
- Codeforces 598D Igor In the Museum(概率DP)
- Codeforces 598D:Igor In the Museum
- codeforces 598D - Igor In the Museum
- CodeForces - 598D Igor In the Museum
- Codeforces 598D Igor In the Museum 【DFS】
- CodeForces 598D Igor In the Museum 暴力
- Codeforces 598D Igor In the Museum (dfs)
- Codeforces 598D Igor In the Museum (DFS)
- CodeForces 598D-Igor In the Museum【DFS】
- Codeforces 598D Igor In the Museum(bfs)
- CodeForces 598D Igor In the Museum【dfs】
- Codeforces 598D Igor In the Museum 离线处理+bfs
- CodeForces 598D Igor In the Museum【dfs】
- CodeForces 598 D. Igor In the Museum(dfs)
- Codeforces 598D Igor In the Museum【预处理Bfs】
- Educational Codeforces Round 1 D. Igor In the Museum
- Educational Codeforces Round 1 D. Igor In the Museum
- Educational Codeforces Round 1 D.Igor In the Museum(DFS)
- gson
- Java图形界面编程学习笔记(一)
- PullToRefreshListView用法
- [nodejs入门]第一篇,javascript基础(3)
- 求助Syntax error, insert "}" to complete
- Codeforces 598D Igor In the Museum(概率DP)
- 创建函数求一个整数是否为素数。
- 探索软件智能高效自动化网络管理的规律
- C#开篇
- 前端css编码规范
- 【cocos2dx】quick cocos2dx 3.5 节点层级太深就会就开始卡
- 在程序里设置加载网页
- java基础随笔-for each对于二维数组的处理
- hdu 1151 最小覆盖路径算法证明