首页 > 代码库 > Aizu 2303 Marathon Match 概率dp

Aizu 2303 Marathon Match 概率dp

题目链接:点击打开链接

题意:

一场马拉松

给定n个运动员,跑道上有m个休息站,马拉松跑道长L

下面n行每行3个参数

表示每个运动员崩溃概率:P 休息时间:E 跑步速度:V。

每个运动员随时会崩溃,崩溃后会坚持到下一个休息站,进入休息他的休息时间。全程匀速运动,可能多次崩溃。

问:

每个运动员成为唯一一个第一名的概率。

思路:

其实可以转换成每个运动员进入下一个休息站的概率是P

每次单独求一个运动员成为第一名的概率。

暴力枚举这个运动员进入休息站的次数。

然后枚举其他的运动员比他慢的概率,相乘得到这个运动员崩溃j次后依然是第一名的概率,相加即是他成为第一名的概率。



#include<bits/stdc++.h>
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
using namespace std;
typedef long long ll;
const int MAXN = 55;
double C[MAXN+1][MAXN+1];
void Initial()
{
    memset(C, 0, sizeof C);
    for(int i=0; i<=MAXN; ++i)
    {
        C[0][i] = 0.0;
        C[i][0] = 1.0;
    }
    for(int i=1; i<=MAXN; ++i)
    {
        for(int j=1; j<=MAXN; ++j)
        C[i][j] = C[i-1][j] + C[i-1][j-1];
    }
}
const int N = 110;
int n, m;
int l, t[N], v[N];
double p[N];
double Pow(double x, int y){
    double ans = 1.0;
    while(y){
        if(y&1)ans *= x;
        x = x*x;
        y >>= 1;
    }
    return ans;
}
double work(int x){
    double ans = 0.0;
    for(int i = 0; i <= m; i++)
    {
        double pp = C[m][i] * Pow(p[x], i) * Pow(1.0-p[x], m-i);
        for(int j = 1; j <= n; j++)
        {
            if(j == x)continue;
            double siz = 0;
            for(int k = m; k >= 0; k--)
            {
                if(l*v[j] + i*t[x]*v[j]*v[x] < l*v[x] + k*t[j]*v[x]*v[j])
                    siz += C[m][k] * Pow(p[j], k) * Pow(1.0-p[j], m-k);
                else break;
            }
            pp *= siz;
        }
        ans += pp;
    }
    return ans;
}
void input(){
    for(int i = 1; i <= n; i++)
        {
            rd(p[i]);rd(t[i]);rd(v[i]);
            p[i] /= 100.0;
        }
}
int main(){
    Initial();
    while(cin>>n>>m>>l){
        input();
        for(int i = 1; i <= n; i++)
            printf("%.10f\n", work(i));
    }
    return 0;
}
/*
30 0 12
0.5
0
13

*/

Marathon Match

Time Limit : 5 sec, Memory Limit : 65536 KB

Marathon Match

N people run a marathon. There are M resting places on the way. For each resting place, the i-th runner takes a break with probability Pi percent. When the i-th runner takes a break, he gets rest for Ti time.

The i-th runner runs at constant speed Vi, and the distance of the marathon is L.

You are requested to compute the probability for each runner to win the first place. If a runner arrives at the goal with another person at the same time, they are not considered to win the first place.

Input

A dataset is given in the following format:

N M L
P1 T1 V1
P2 T2 V2

PN TN VN

The first line of a dataset contains three integers N (1N100), M (0M50) and L(1L100,000). N is the number of runners. M is the number of resting places. L is the distance of the marathon.

Each of the following N lines contains three integers Pi (0Pi100), Ti (0Ti100) and Vi(0Vi100) describing the i-th runner. Pi is the probability to take a break. Ti is the time of resting. Vi is the speed.

Output

For each runner, you should answer the probability of winning. The i-th line in the output should be the probability that the i-th runner wins the marathon. Each number in the output should not contain an error greater than 10?5.

Sample Input 1

2 2 50
30 50 1
30 50 2

Output for the Sample Input 1

0.28770000
0.71230000

Sample Input 2

2 1 100
100 100 10
0 100 1

Output for the Sample Input 2

0.00000000
1.00000000

Sample Input 3

3 1 100
50 1 1
50 1 1
50 1 1

Output for the Sample Input 3

0.12500000
0.12500000
0.12500000

Sample Input 4

2 2 50
30 0 1
30 50 2

Output for the Sample Input 4

0.51000000
0.49000000


Aizu 2303 Marathon Match 概率dp