把两种状态化成2*n-2的一条线上的一种状态即可。很容易想到。

高斯列主元法,不知为什么WA。要上课了,不玩了。。。逃了一次课呢。。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
double const eps=1e-8;
double G[210][210]; int n,m,s,e,d; double sum;
double pk[110];
double ans[210];
bool vis[210];
bool find(int i){
int k=i;
for(int j=i+1;j<n;j++){
if(fabs(G[j][i])>fabs(G[k][i]))
k=j;
}
if(fabs(G[k][i])<eps) return false;
for(int p=i;p<=n;p++)
swap(G[i][p],G[k][p]);
return true;
} bool Guass(){
for(int i=0;i<n;i++){
if(find(i)){
for(int j=i+1;j<n;j++){
double k=G[j][i]/G[i][i];
for(int p=i;p<=n;p++)
G[j][p]=G[j][p]-k*G[i][p];
}
}
else return false;
} ans[n-1]=G[n-1][n]/G[n-1][n-1];
for(int i=n-2;i>=0;i--){
double sum=0;
for(int j=n-1;j>i;j--){
sum+=(G[i][j]*ans[j]);
}
ans[i]=(G[i][n]-sum)/G[i][i];
}
return true;
} bool BFS(int s){
queue<int>q;
q.push(s);
memset(vis,false,sizeof(vis));
vis[s]=true;
while(!q.empty()){
int te=q.front();
q.pop();
for(int i=1;i<=m;i++){
if(pk[i]<eps)
continue;
int u=(te+i)%n;
if(!vis[u]){
vis[u]=true;
q.push(u);
if(u==e||u==n-e) return true;
}
}
}
return false;
} int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&n,&m,&e,&s,&d);
sum=0;
n=2*n-2;
for(int i=1;i<=m;i++){
scanf("%lf",&pk[i]);
pk[i]/=100;
sum+=(i*pk[i]);
}
if (s == e){
puts ("0.00");
continue;
}
if(d==0) s=s;
else if(d==1) s=(n-s)%n;
memset(G,0,sizeof(G));
for(int i=0;i<n;i++){
G[i][i]=-1;
if(i==e||i==n-e) continue;
for(int j=1;j<=m;j++){
if(pk[j]<eps)
G[i][(j+i)%n]=pk[j];
}
G[i][n]=-sum;
}
if(!BFS(s)){
puts("Impossible !");
continue;
}
if(!Guass()){
puts("Impossible !");
}
else{
printf("%.2f\n",ans[s]);
}
}
return 0;
}

  

  这个是别人的

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <algorithm>
#include <math.h>
using namespace std;
#define M 205
#define eps 1e-8
int equ, var;
double a[M][M], x[M]; int Gauss ()
{
int i, j, k, col, max_r;
for (k = 0, col = 0; k < equ && col < var; k++, col++)
{
max_r = k;
for (i = k+1; i < equ; i++)
if (fabs (a[i][col]) > fabs (a[max_r][col]))
max_r = i;
if (k != max_r)
{
for (j = col; j < var; j++)
swap (a[k][j], a[max_r][j]);
swap (x[k], x[max_r]);
}
x[k] /= a[k][col];
for (j = col+1; j < var; j++) a[k][j] /= a[k][col];
a[k][col] = 1;
for (i = 0; i < equ; i++) if (i != k)
{
x[i] -= x[k] * a[i][k];
for (j = col+1; j < var; j++) a[i][j] -= a[k][j] * a[i][col];
a[i][col] = 0;
}
}
return 1;
} //has[x]表示人在x点时的变量号,因为我们只用可达状态建立方程,所以需要编号
int has[M], vis[M], k, e, n, m;
double p[M], sum; int bfs (int u)
{
memset (has, -1, sizeof(has));
memset (a, 0, sizeof(a)); //忘记初始化WA勒,以后得注意
memset (vis, 0, sizeof(vis));
int v, i, flg = 0;
queue<int> q;
q.push (u);
k = 0;
has[u] = k++;
while (!q.empty ())
{
u = q.front ();
q.pop ();
if (vis[u]) continue;
vis[u] = 1;
if (u == e || u == n-e) //终点有两个,你懂的~
{
a[has[u]][has[u]] = 1;
x[has[u]] = 0;
flg = 1;
continue;
}
//E[x] = sum ((E[x+i]+i) * p[i])
// ----> E[x] - sum(p[i]*E[x+i]) = sum(i*p[i])
a[has[u]][has[u]] = 1;
x[has[u]] = sum;
for (i = 1; i <= m; i++)
{
//非常重要!概率为0,该状态可能无法到达,如果还去访问并建立方程会导致无解
if (fabs (p[i]) < eps) continue;
v = (u + i) % n;
if (has[v] == -1) has[v] = k++;
a[has[u]][has[v]] -= p[i];
q.push (v);
}
}
return flg;
} int main()
{
int t, s, d, i;
scanf ("%d", &t);
while (t--)
{
scanf ("%d%d%d%d%d", &n, &m, &e, &s, &d);
n = 2*(n-1);
sum = 0;
for (i = 1; i <= m; i++)
{
scanf ("%lf", p+i);
p[i] = p[i] / 100;
sum += p[i] * i;
}
if (s == e)
{
puts ("0.00");
continue;
}
//一开始向左,起点要变
if (d > 0) s = (n - s) % n;
if (!bfs (s))
{
puts ("Impossible !");
continue;
}
equ = var = k; Gauss ();
printf ("%.2f\n", x[has[s]]);
}
return 0;
}

  

05-21 22:53