1. 程式人生 > >【Codeforces Round 331 (Div 2)D】【DP 記憶化搜尋 期望DP區間性質 好題】Wilbur and Trees 砍樹隨機從右從左概率左倒右倒的期望底面覆蓋長度

【Codeforces Round 331 (Div 2)D】【DP 記憶化搜尋 期望DP區間性質 好題】Wilbur and Trees 砍樹隨機從右從左概率左倒右倒的期望底面覆蓋長度

Wilbur and Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Wilbur the pig really wants to be a beaver, so he decided today to pretend he is a beaver and bite at trees to cut them down.

There arentrees located at various positions on a line. Treeiis located at positionxi. All the given positions of the trees are distinct.

The trees are equal, i.e. each tree has heighth

. Due to the wind, when a tree is cut down, it either falls left with probabilityp, or falls right with probability1 - p. If a tree hits another tree while falling, that tree will fall in the same direction as the tree that hit it. A tree can hit another tree only if the distance between them is strictly less thanh
.

For example, imagine there are4trees located at positions1,3,5and8, whileh = 3and the tree at position1falls right. It hits the tree at position3and it starts to fall too. In it's turn it hits the tree at position5and it also starts to fall. The distance between8and5is exactly3, so the tree at position8

will not fall.

As long as there are still trees standing, Wilbur will select either the leftmost standing tree with probability0.5or the rightmost standing tree with probability0.5. Selected tree is then cut down. If there is only one tree remaining, Wilbur always selects it. As the ground is covered with grass, Wilbur wants to know the expected total length of the ground covered with fallen trees after he cuts them all down because he is concerned about his grass-eating cow friends. Please help Wilbur.

Input

The first line of the input contains two integers,n(1 ≤ n ≤ 2000)andh(1 ≤ h ≤ 108)and a real numberp(0 ≤ p ≤ 1), given with no more than six decimal places.

The second line of the input containsnintegers,x1, x2, ..., xn( - 108 ≤ xi ≤ 108)in no particular order.

Output

Print a single real number — the expected total length of the ground covered by trees when they have all fallen down. Your answer will be considered correct if its absolute or relative error does not exceed10 - 6.

Namely: let's assume that your answer isa, and the answer of the jury isb. The checker program will consider your answer correct, if.

Sample test(s) input
2 2 0.500000
1 2
output
3.250000000
input
4 3 0.4
4 3 1 2
output
6.631200000
Note

Consider the first example, we have 2 trees with height 2.

There are 3 scenarios:

1. Both trees falls left. This can either happen with the right tree falling left first, which hasprobability (also knocking down the left tree), or the left tree can fall left and then the right tree can fall left, which hasprobability. Total probability is.

2. Both trees fall right. This is analogous to (1), so the probability of this happening is.

3. The left tree fall left and the right tree falls right. This is the only remaining scenario so it must haveprobability.

Cases 1 and 2 lead to a total of 3 units of ground covered, while case 3 leads to a total of 4 units of ground covered. Thus, the expected value is.

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=2000+5,M=0,Z=1e9+7,ms63=1061109567;
int n,h;double p;
int a[N];
int lft[N],rgt[N];
double f[2][N][N][2];
double dl[N][2],dr[N][2];
double dp(bool bl,int l,int r,bool br)
{
	if(l>r)return 0;
	if(f[bl][l][r][br]>-1)return f[bl][l][r][br];

	/*//不帶初始化的寫法
	double pll=(bl?min(2*h,a[l]-a[l-1])-h:min(h,a[l]-a[l-1]))+dp(0,l+1,r,br);
	double prr=(br?min(h,a[r+1]-a[r]):min(2*h,a[r+1]-a[r])-h)+dp(bl,l,r-1,1);
	double plr=rgt[l]>=r?
		(a[r]-a[l]+(br?min(h,a[r+1]-a[r]):min(2*h,a[r+1]-a[r])-h)):
		(a[rgt[l]]-a[l]+h+dp(1,rgt[l]+1,r,br));
	double prl=lft[r]<=l?
		(a[r]-a[l]+(bl?min(2*h,a[l]-a[l-1])-h:min(h,a[l]-a[l-1]))):
		(a[r]-a[lft[r]]+h+dp(bl,l,lft[r]-1,0));*/

	//經過初始化的寫法
	double pll=dl[l][bl]+dp(0,l+1,r,br);
	double prr=dr[r][br]+dp(bl,l,r-1,1);
	double plr=rgt[l]>=r?a[r]-a[l]+dr[r][br]:a[rgt[l]]-a[l]+h+dp(1,rgt[l]+1,r,br);
	double prl=lft[r]<=l?a[r]-a[l]+dl[l][bl]:a[r]-a[lft[r]]+h+dp(bl,l,lft[r]-1,0);
	return f[bl][l][r][br]=0.5*p*(pll+prl)+0.5*(1-p)*(plr+prr);
	
}
int main()
{
	while(~scanf("%d%d%lf",&n,&h,&p))
	{
		for(int i=1;i<=n;++i)scanf("%d",&a[i]);
		sort(a+1,a+n+1);a[0]=-1e9;a[n+1]=1e9;
		//預處理一棵樹向左向右倒能使得一起倒的最左最右的那棵樹的標號,分別即為lft[i],rgt[i]
		for(int i=1;i<=n;++i)
		{
			if(a[i]-a[i-1]<h)lft[i]=lft[i-1];
			else lft[i]=i;
		}
		for(int i=n;i>=1;--i)
		{
			if(a[i+1]-a[i]<h)rgt[i]=rgt[i+1];
			else rgt[i]=i;
		}
		//預處理——DP的記憶化陣列初始化為-1
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=n;++j)
			{
				f[0][i][j][0]=f[0][i][j][1]=f[1][i][j][0]=f[1][i][j][1]=-1;
			}
		}
		//預處理,i點向左倒與i-1的貢獻,或i向右倒與i+1的貢獻
		for(int i=1;i<=n;++i)
		{
			dl[i][0]=min(a[i]-a[i-1],h);
			dl[i][1]=min(a[i]-a[i-1],h*2)-h;
			dr[i][0]=min(a[i+1]-a[i],h*2)-h;
			dr[i][1]=min(a[i+1]-a[i],h);
		}
		printf("%.15f\n",dp(0,1,n,1));
	}
	return 0;
}
/*
【trick&&吐槽】
1,DP真是太有趣啦!
2,bool?a:b這個三目運算子中,?和:的優先順序都比較低。
	於是,如果還有外部運算,我們可以寫成(bool?a:b)的形式。

【題意】
有n(1<=n<=2000)棵樹,每棵樹所在的位置為a[](-1e8<=a[i]<a[i+1]<=1e8),所有樹的高度都為h(1<=h<=1e8)。
每棵樹倒下時,向左倒的概率為p,向右倒的概率為1-p。
每棵樹倒之後會帶來連鎖反應,使得能觸及的樹一起倒。
我們想要砍倒所有的樹。只要還有樹,我們就會要不砍倒最左邊的那棵,要不砍倒最右邊的那棵。砍左還是砍右概率都是0.5
想問你,最後樹倒下所覆蓋的線段長度的期望是多少。

【型別】
區間DP

【分析】
首先,有些東西我們是可以預處理的——
對於第i一棵樹,如果這棵樹向左或向右倒,會一直影響使得第幾棵樹倒下,記在lft[i]或者rgt[i]

然後,我們看到n只有2000,於是這道題大概可以通過一個O(n^2)的DP求解。
我們想解決大的問題,可以把每個問題都轉換為子問題,遞迴解決。

那麼首要問題就是如何定義狀態
首先,肯定有(l,r)。
然後,我們發現我們還需要知道第l-1和第r+1的兩棵樹的狀態,因為——
1,這兩棵樹一定是先倒的
2,這兩棵樹倒向的方向,對線段覆蓋的長度統計會有影響。

於是,狀態的定義就變成了(l,r,bl,br)
依次表示這個區間的左右範圍,左邊的樹的倒向,右邊的樹的倒向。
bl==0表示左樹向左倒,bl==1表示左樹向右倒
br==0表示右樹向左倒,br==1表示右樹向右倒

那麼我們有——dp(L,R,0,1)就是答案。
具體的DP方程如何設計呢?
首先,砍l還是r的概率都是0.5,向左倒和向右倒的概率分別是p和1-p,於是答案就是
0.5*p*(砍l,l向左倒)+
0.5*(1-p)*(砍l,l向右倒)+
0.5*p*(砍r,r向左倒)+
0.5*(1-p)*(砍r,r向右倒)
=0.5*p*(砍l向左倒+砍r向左倒)+0.5*(1-p)*(砍l向右倒+砍r向右倒)

四部分的權值如何算呢?具體在程式碼中解釋~~~~
於是,還是老樣子的做法——設狀態,找轉移,就AC啦!啦啦啦啦!

【時間複雜度&&優化】
O(n^2)

【資料】
input
2 2 0.5
1 2
因為p=0.5,所以第一刀砍哪棵樹都一樣,於是假設第一刀砍第一棵樹。
那麼第一棵樹向左倒0.5
	第二棵樹向左:3	第二棵樹向右:4
	第一棵樹向右倒0.5
	第二棵樹向右:3
於是最後期望就是0.5*3.5+0.5*3=3.25

*/


相關推薦

Codeforces Round #459 (Div. 2) D. MADMAX 博弈和記憶搜尋(同時照顧兩個起點的記憶搜尋

D. MADMAXtime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputAs we all know, Max is the b

Codeforces Round 331 (Div 2)DDP 記憶搜尋 期望DP區間性質 Wilbur and Trees 隨機概率期望覆蓋長度

Wilbur and Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard ou

Codeforces Round #406 (Div. 2):C. Berzerk(記憶搜尋解決博弈問題)

Each one of them has a set of numbers between 1 and n - 1 (inclusive). Rick's set is s1 with k1 elements and Morty's is s2 with k2 elements. One of th

Codeforces Round #451 (Div. 2) DAlarm Clock

force alarm cnblogs bit any inpu size class long long 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 尺取法+二分。 類似滑動窗口。 即左端點為l,右端點為r. 維護a[r]-a[l]

Codeforces Round #508 (Div. 2) D. Slime思維

D. Slime time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There are 

Codeforces Round #514 (Div. 2) D. Nature Reserve 三分+推公式

HEU 大三蒟蒻一枚 有任何問題或建議都可以加Q聯絡我^_^ QQ : 986195894 CodeForces id : lajiyuan CodeForces id : biubiubiu_ Vjudge id : heu2016201206

Codeforces Round #338 (Div. 2)D. Multipliers費馬小定理+組合數學

D. Multipliers time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Codeforces Round 365 (Div 2)D離線詢問 狀陣列 前驅思想Mishka and Interesting sum 區間內出現次數偶數的數的異或和

Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present her with array of non-negative integersa1, a2, ..., 

分類討論spfaBFSCodeforces Round #416 (Div. 2) D. Vladik and Favorite Game

邊界情況 code def bfs spa eof scan string amp 那個人第一步肯定要麽能向下走,要麽能向右走。於是一定可以判斷出上下是否對調,或者左右是否對調。 然後他往這個方向再走一走就能發現一定可以再往旁邊走,此時就可以判斷出另一個方向是否對調。 都判

推導Codeforces Round #364 (Div. 2) D. As Fast As Possible

std %d while pre 分享 mage oss 時間 http 一種方法是二分總時間,復雜度O(nlogn)。 另外我們可以證明,當所有人同時到達終點的時候,是最優的,因為沒有人的時間“浪費”了。 我們又發現,每個人的運動過程總是兩段,要麽是走路,要麽是坐車。於

排序規律Codeforces Round #254 (Div. 2) - D. Rooter's Song

names nes rac then represent cin loaded output same D. DZY Loves FFT Source http://codeforces.com/contest/445/problem/D Description Wh

偽暴力+智商剪枝Codeforces Round #489 (Div. 2) D

profile 接下來 時間 一個數 鏈表 數字 sum 方式 print 失蹤人口突然回歸……orz。題解還是有必要寫的,雖然估計只有自己(?自己也不一定看得懂)看得懂。 題目鏈接:http://codeforces.com/contest/992/problem/D

Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) D. Minimum pathdp+滾動陣列

D. Minimum path 題意 給你一個字元矩陣,起點在左上角,每次可以向右或者向下走,可以改變這個字元矩陣中的k個字元,是這個路徑構成的字串字典序最小。 做法 由於可以改變k個字元,那麼肯定是找到一條路徑,前面至少有k項為a, 後面按照字典序選擇路徑就可以。 所

Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) A.B.C.D

前言 在晚上的div2之前開啟的這場,但是自己頭腦貌似不太清醒,全程在寫bug,而且B題不知道自己在寫啥,寫了一百多行?,C也寫了好多bug導致最後的D一眼思路但是沒寫完。希望晚上狀態不要這麼差!QWQ A. Golden Plate 題意 給你一個h*w的長方形邊框,

Codeforces Round #509 (Div. 2)A,B,C,D

這是蒟蒻的真·第一場CF...所以其實升了1500+還是不錯吧? 題意:找包含給出的n個數的最短連續序列,輸出新加入的數的最小個數。 分析:排序+掃描即可。 #include<i

map離散&容斥Ghosts @Codeforces Round #478 (Div. 2) D

傳送門 題意:給你一條直線的斜率a和截距b,和某一時刻n個在直線上的點的橫座標,以及沿座標軸方向的速度。問你這些點在(-∞,+∞)的時間內的碰撞次數。 solution 設兩個點在t時刻相碰,有:

Codeforces Round #538 (Div. 2) D. Flood Fill 區間dp || LPS (最長回文序列)

最長 tle res connected byte ima title aps 例如 任意門:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds

Codeforces Round #447 (Div. 2) AQAQ

pro ont 題解 problem fde c語言 span bits endif 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 C語言程序練習題 【代碼】 #include <bits/stdc++.h> using

Codeforces Round #456 (Div. 2) CPerun, Ult!

set != bound names begin pre round 部分 之前 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 set1 < pair < int,int > > set1;記錄關鍵點->某

Codeforces Round #457 (Div. 2) A Jamie and Alarm Snooze

als lar clu efi out .com bit source fin 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 暴力往前走x分鐘就好。 直到出現7為止。 【代碼】 #include <bits/stdc++.h&