
2 4 2 0 1 0 50 50 4 1 0 2 1 100
8.14 2.00
Statistic | Submit | Discuss | Note
很明显的概率dp,设dp[i]表示在点i的时候达到终点的期望步数
dp[i] = p1 * (dp[i + 1] + 1) + p2 * (dp[i + 2] + 2) + ...+ pm * (dp[i + m] + m);
当然 dp[e] = 0;
但是由于方向有2个,所以我们要把反着走的状态变成正着走,也就是把路对称一下, 012345 -》 0123456789
这样 比如 4 走到 3就变成了6走到7,方向就固定了,然后就可以建立线性方程组求解了,注意有些点到不了,这个得先用bfs处理一下,顺便给每一个可到的点编号,然后高斯消元就行了
/*************************************************************************
> File Name: hdu4418.cpp
> Author: ALex
> Mail: 405045132@qq.com
> Created Time: 2014年12月29日 星期一 17时01分42秒
************************************************************************/
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 210;
const double eps = 1e-12;
double sum_p;
double mat[N][N], x[N];
double p[N];
bool free_x[N];
int ord[N];
int n, m, s, e, cnt;
int Gauss()
{
int col, k, equ, var, max_r;
int free_index, free_num;
equ = cnt;
var = cnt;
k = col = 0;
for (int i = 0; i < var; ++i)
{
free_x[i] = true;
x[i] = 0;
}
for (; k < equ && col < var; ++k, ++col)
{
max_r = k;
for (int i = k + 1; i < equ; ++i)
{
if (fabs(mat[i][col]) - fabs(mat[max_r][col]) > eps)
{
max_r = i;
}
}
if (max_r != k)
{
for (int j = k; j < var + 1; ++j)
{
swap(mat[k][j], mat[max_r][j]);
}
}
if (fabs(mat[k][col]) <= eps)
{
--k;
continue;
}
for (int i = k + 1; i < equ; ++i)
{
double tmp = mat[i][col] / mat[k][col];
for (int j = col; j < var + 1; ++j)
{
mat[i][j] -= tmp * mat[k][j];
}
}
}
//判断解的情况
for (int i = k; i < equ; ++i)
{
if (fabs(mat[i][var]) > eps)
{
return 0;
}
}
if (k < var)
{
for (int i = k - 1; i >= 0; --i)
{
free_num = 0;
for (int j = 0; j < var; ++j)
{
if (fabs(mat[i][j]) > eps && free_x[j])
{
free_num++;
free_index = j;
}
}
if (free_num > 1)
{
continue;
}
double tmp = mat[i][var];
for (int j = 0; j < var; ++j)
{
if (fabs(mat[i][j]) > eps && j != free_index)
{
tmp -= mat[i][j] * x[j];
}
}
free_x[free_index] = false;
x[free_index] = tmp / mat[i][free_index];
}
return var - k;
}
for (int i = var - 1; i >= 0; --i)
{
double tmp = mat[i][var];
for (int j = i + 1; j < var; ++j)
{
if (fabs(mat[i][j]) > eps)
{
tmp -= x[j] * mat[i][j];
}
}
x[i] = tmp / mat[i][i];
}
return 1;
}
void bfs()
{
cnt = 0;
queue <int> qu;
memset (ord, -1, sizeof(ord));
ord[s] = cnt++;
while (!qu.empty())
{
qu.pop();
}
qu.push(s);
while (!qu.empty())
{
int u = qu.front();
qu.pop();
for (int i = 1; i <= m; ++i)
{
if (p[i] <= eps)
{
continue;
}
int v = (i + u) % n;
if (ord[v] == -1)
{
ord[v] = cnt++;
qu.push(v);
}
}
}
}
void build()
{
for (int i = 0; i < n; ++i)
{
if (ord[i] == -1)
{
continue;
}
if (i == e || i == (n - e) % n)
{
mat[ord[i]][ord[i]] = 1;
mat[ord[i]][cnt] = 0;
continue;
}
mat[ord[i]][ord[i]] = 1.0;
for (int j = 1; j <= m; ++j)
{
if (ord[(i + j) % n] == -1)
{
continue;
}
mat[ord[i]][ord[(i + j) % n]] -= p[j];
}
mat[ord[i]][cnt] = sum_p;
}
}
int main()
{
int t, D;
scanf("%d", &t);
while (t--)
{
sum_p = 0;
memset (mat, 0, sizeof(mat));
scanf("%d%d%d%d%d", &n, &m, &e, &s, &D);
n = 2 * n - 2;
for (int i = 1; i <= m; ++i)
{
scanf("%lf", &p[i]);
p[i] /= 100.0;
sum_p += i * p[i];
}
if (s == e || n == 1)
{
printf("0.00\n");
continue;
}
if (D > 0)
{
s = (n - s) % n;
}
bfs();
if (ord[e] == -1 && ord[(n - e) % n] == -1)
{
printf("Impossible !\n");
continue;
}
build();
if (!Gauss())
{
printf("Impossible !\n");
continue;
}
printf("%.2f\n", x[ord[s]]);
}
return 0;
}原文:http://blog.csdn.net/guard_mine/article/details/42242499