标签:else clu tree print can dir 方向 turn 严格
题意:有一些高度为h的树在数轴上。每次选择剩下的树中最左边或是最右边的树推倒(各50%概率),往左倒有p的概率,往右倒1-p。
一棵树倒了,如果挨到的另一棵树与该数的距离严格小于h,那么它也会往同方向倒。
问所有树都被推倒后的期望覆盖长度?
n<=2000.
标程:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int inf=1e8+5; 6 const int N=2005; 7 int pos[N],h,n,L[N],R[N]; 8 double p,dp[N][N][2][2]; 9 int check(int op,int x,int dir) 10 { 11 if (op==0) 12 { 13 if (!dir) return min(pos[x]-pos[x-1],h); 14 else return min(h,max(pos[x]-pos[x-1]-h,0)); 15 }else { 16 if (!dir) return min(h,max(pos[x+1]-pos[x]-h,0)); 17 else return min(pos[x+1]-pos[x],h); 18 } 19 } 20 double dfs(int x,int y,int l,int r) 21 { 22 if (x>y) return 0; 23 if (dp[x][y][l][r]) return dp[x][y][l][r]; 24 double &ans=dp[x][y][l][r]; 25 //choose left 26 ans+=0.5*p*(dfs(x+1,y,0,r)+check(0,x,l));//fall left 27 if (R[x]+1<=y) ans+=0.5*(1-p)*(dfs(R[x]+1,y,1,r)+pos[R[x]]-pos[x]+h);//fall right 28 else ans+=0.5*(1-p)*(pos[y]-pos[x]+check(1,y,r)); 29 //choose right 30 ans+=0.5*(1-p)*(dfs(x,y-1,l,1)+check(1,y,r));//fall right 31 if (x<=L[y]-1) ans+=0.5*p*(dfs(x,L[y]-1,l,0)+pos[y]-pos[L[y]]+h);//fall left 32 else ans+=0.5*p*(pos[y]-pos[x]+check(0,x,l)); 33 return ans; 34 } 35 int main() 36 { 37 scanf("%d%d%lf",&n,&h,&p); 38 for (int i=1;i<=n;i++) scanf("%d",&pos[i]); 39 sort(pos+1,pos+n+1);pos[0]=pos[1]-h;pos[n+1]=pos[n]+h; 40 L[1]=1;R[n]=n; 41 for (int i=2;i<=n;i++) 42 if (i==1||pos[i]-pos[i-1]<h) L[i]=L[i-1];else L[i]=i; 43 for (int i=n-1;i>=1;i--) 44 if (i==n||pos[i+1]-pos[i]<h) R[i]=R[i+1];else R[i]=i; 45 printf("%.10lf\n",dfs(1,n,0,1)); 46 return 0; 47 }
易错点:1.注意长度的判断。分类讨论。
2.需要设置极值端点,和1树、n树的距离要>=h。
题解:区间dp
剩下的一段树一定是连续的,区间dp即可。分四种情况讨论推导情况。
预处理一棵树往左/往右倒影响多少棵树。注意计算距离。
标签:else clu tree print can dir 方向 turn 严格
原文地址:https://www.cnblogs.com/Scx117/p/8799173.html