Codeforces 16E Fish 概率DP

这一场好水啊。。这题算是比较简单的概率DP了吧,外加一点状压。

dp[sta] = sigma (dp[sta|(1<<i)]*val[j][i]/( (ans+1)*ans/2 ) ),(i为sta已被吃掉的,j为存活的,ans为存活的个数)。

之所以要除( (ans+1)*ans/2 ),是因为在ans+1条鱼中一共有这些对,且这些对等概率。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007

/** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
    char c;
    while(!d);
    x=c-'0';
    while(d)p;
    return x;
}
template<class T> inline T& RDD(T &x)
{
    char c;
    while(g,c!='-'&&!isdigit(c));
    if (c=='-')
    {
        x='0'-g;
        while(d)n;
    }
    else
    {
        x=c-'0';
        while(d)p;
    }
    return x;
}
inline double& RF(double &x)      //scanf("%lf", &x);
{
    char c;
    while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.')
        {
            x=0;
            double l=1;
            while(d)nn;
            x*=l;
        }
        else
        {
            x='0'-c;
            while(d)n;
            if(c=='.')
            {
                double l=1;
                while(d)nn;
                x*=l;
            }
        }
    else if(c=='.')
    {
        x=0;
        double l=1;
        while(d)pp;
        x*=l;
    }
    else
    {
        x=c-'0';
        while(d)p;
        if(c=='.')
        {
            double l=1;
            while(d)pp;
            x*=l;
        }
    }
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;

double val[20][20];

double dp[1<<18];

bool vis[20];

double dfs(int sta,int n,int ans)
{
    if(dp[sta] > -0.5)
        return dp[sta];

    dp[sta] = 0;

    int i,j;
    double tmp;

    for(i = 0;i < n; ++i)
    {
        if(vis[i] == false)
        {
            vis[i] = true;
            tmp = dfs(sta|(1<<i),n,ans+1);
            vis[i] = false;

            for(j = 0;j < n; ++j)
                if(vis[j])
                    dp[sta] += tmp*val[j][i]/((ans+1)*ans/2.0);
        }
    }

    return dp[sta];
}

int main()
{
    int n,i,j;

    scanf("%d",&n);

    for(i = 0;i < n; ++i)
        for(j = 0;j < n; ++j)
            scanf("%lf",&val[i][j]);

    memset(dp,-1,sizeof(dp));
    dp[(1<<n)-1] = 1;
    memset(vis,false,sizeof(vis));

    for(i = 0;i < n; ++i)
    {
        vis[i] = true;
        dp[1<<i] = dfs(1<<i,n,1);
        vis[i] = false;
    }

    for(i = 0;i < n; ++i)
        printf("%.10lf ",dp[1<<i]);

    return 0;
}
时间: 2024-08-29 21:24:19

Codeforces 16E Fish 概率DP的相关文章

Codeforces 16E Fish

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

codeforces 148D 【概率dp】

题目链接: codeforces 148D Bag of mice 题意:一个包里面有w只白老鼠和b只黑老鼠,公主与龙依次从包中拿老鼠,每次取一只,当龙拿时还会从包中溜走一只,先拿到老鼠的获胜,当背包中没老鼠时且之前没人拿到白老鼠则龙获胜,问公主获胜的概率是多少. 题解: 设dp[i][j]为背包中有i只白老鼠j只黑老鼠时公主获胜的概率 则公主获胜的情况分成三种: 1.直接拿到白老鼠 p1=i/(i+j) 2.公主拿到黑老鼠,龙拿到黑老鼠,逃跑一只黑老鼠 p2=(j/(i+j)) ((j-1)/

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=

CodeForces 540D Bad Luck Island 概率dp

CodeForces 540D 应该是简单概率dp,由于写得少显得十分蠢萌 求期望逆推,求概率正推,大概是这么个意思,贴一发留恋 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define db double const int maxn=108; db dp[maxn][maxn][maxn]; int main() { int i,j,n,m,k,p; whi

Codeforces 148D Bag of mice (概率dp)

D. Bag of mice time limit per test:2 seconds memory limit per test:256 megabytes The dragon and the princess are arguing about what to do on the New Year's Eve. The dragon suggests flying to the mountains to watch fairies dancing in the moonlight, wh

Codeforces 518D Ilya and Escalator (概率dp)

Ilya and Escalator time limit per test: 2 seconds memory limit per test: 256 megabytes Ilya got tired of sports programming, left university and got a job in the subway. He was given the task to determine the escalator load factor. Let's assume that

codeforces 235B Let&#39;s Play Osu! 概率dp

题意:给定n表示有n个格子,下面每个格子为O的概率是多少.对于一段连续 x 个O的价值就是 x^2 ;求获得的价值的期望是多少. 思路:n^2=n×(n-1)+n,设ai为第i段连续O的长度,∑ai^2 = ∑[ ai+ ai*(ai-1) ] = ∑ ai*(ai-1) + ∑ai = ∑ C(ai, 2)*2 + ∑ai,那么问题可以转 化为求长度大于1的连续段数*2+O的个数的总期望. ∑ai我们可以理解为O的总个数,所以它的期望为∑pi: C(ai, 2)*2我们可以认 为是连续ai个O

Codeforces 235B Let&#39;s Play Osu! (概率dp求期望+公式变形)

B. Let's Play Osu! time limit per test:2 seconds memory limit per test:256 megabytes You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us deno

Codeforces 235B Let&#39;s Play Osu! 概率dp(水

题目链接:点击打开链接 给定n表示有n个格子 下面每个格子为O的概率是多少. 对于一段连续 x 个O的价值就是 x*x ; 问: 获得的价值的期望是多少. 思路: 把公式拆一下.. #include <cstdio> const int N = 100005; double dp[N][2], p[N]; int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("