刷题总结——随机图(ssoi)

题目:

 随机图
(random.cpp/c/pas)
【问题描述】
BG 为了造数据,随机生成了一张�个点的无向图。他把顶点标号为1~�。
根据BG 的随机算法,对于一个点对�, �(1 ≤ � < � ≤ �),它有�‰(千分之�)的概率成为
这张图中的一条边� − �。不同的边出现的概率是相互独立的。
为了保证数据的强度,BG要求生成的图中至少要有一个大于等于 4的连通块。于是他
想知道,在不做任何改进的情况下,根据他的算法造出强数据的概率是多少。

【输入】
输入文件名为random.in。
共一行两个整数�, �,中间用一个空格隔开,表示图的点数和边在图上的概率。

【输出】
输出文件名为random.out。
输出共一行一个实数,表示所求的概率。结果保留4 位小数。 【输入输出样例1】 

random.in random.out
3 123

0.0000


【输入输出样例2】
random.in random.out
4 500

0.5938

题解:�

 

概率DP方程

�[�+1][�−1][�+1],乘上系�·(1−�)�

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=105;
double dp[N][N][N],p,ans=1;
double c[N][2];
int n;
inline void pre()
{
  for(int i=1;i<=n;i++)  c[i][1]=i; 
  for(int i=2;i<=n;i++)
    for(int j=2;j<=n;j++)
      c[i][j]=c[i-1][j]+c[i-1][j-1];
}
int main()
{
  scanf("%d",&n);
  cin>>p;
  p=p/1000;
  pre();
  dp[0][0][0]=1;
  for(int i=0;i<=n;i++)
    for(int j=0;j<=n/2;j++)
      for(int k=0;k<=n/3;k++)
      {
        int l=(i-2*j-3*k);
        dp[i+1][j][k]+=dp[i][j][k]*pow(1-p,i);
        dp[i+1][j+1][k]+=dp[i][j][k]*pow(1-p,i-1)*l*p;
        dp[i+1][j][k+1]+=dp[i][j][k]*c[l][2]*pow(1-p,i-2)*p*p;
        dp[i+1][j-1][k+1]+=dp[i][j][k]*pow(1-p,i-1)*2*j*p; 
        dp[i+1][j-1][k+1]+=dp[i][j][k]*pow(1-p,i-2)*j*p*p;
      }
  for(int j=0;j<=n/2;j++)
    for(int k=0;k<=n/3;k++) 
      ans-=dp[n][j][k];
  printf("%0.4lf",ans);
  return 0;
}

 

� ≤ 1,000。

posted @ 2017-07-07 16:02  AseanA  阅读(368)  评论(0编辑  收藏  举报