设dp[i]为处在格子i走到格子N时的期望,很容易得出方程,但是存在后退操作,所以方程中会存在dp[j]其中j<i,不能直接递推需要用高斯消元解方程组。可以先用DFS标记出能到达的点,然后按照这些能达到的点列出方程组,然后解方程即可。
/*
author : csuchenan
prog : POJ 3756
algorithm: 高斯消元+期望
csuchenan 3756 Accepted 252K 16MS C++ 3454B
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#define eps 1e-9
#define INF 0x3f3f3f3f
const int maxn = 100;
double martix[maxn+5][maxn+5];
double ans[maxn+5];
int fp[maxn+5], index[maxn];
bool reach[maxn+5];
int n;
int getNext(int v, int d){
int p = v + d;
if(p < 0 || p > n){
p = n - (p%n + n)%n;
}
return p;
}
void dfs(int v){
reach[v] = true;
for(int i = 1; i <= 6; i ++){
int p = getNext(v, i);
if(fp[p]!= INF)
p = getNext(p, fp[p]);
if(!reach[p]){
dfs(p);
}
}
}
void read(){
int nf, tv, tu;
memset(fp, 0x3f, sizeof(fp));
scanf("%d", &n);
scanf("%d", &nf);
for(int i = 0; i < nf; i ++){
scanf("%d%d", &tv, &tu);
fp[tv] = tu;
}
scanf("%d", &nf);
for(int i = 0; i < nf; i ++){
scanf("%d%d", &tv, &tu);
fp[tv] = -tu;
}
scanf("%d", &nf);
for(int i = 0; i < nf; i ++){
scanf("%d", &tv);
fp[tv] = 0;
}
}
void swap(double &x, double &y){
double t = y;
y = x;
x = t;
}
double gauss(int x){
int i, j, k, p;
for(i = 0; i < x; i ++){
p = i;
for(j = i + 1 ; j < x ; j ++){
if(fabs(martix[p][i]) < fabs(martix[j][i])){
p = j;
}
}
if(fabs(martix[p][i]) < eps){
continue;
}
if(p != i){
for(j = i; j <= x; j ++){
swap(martix[p][j], martix[i][j]);
}
}
for(j = i + 1; j < x; j ++){
double r = martix[j][i]/martix[i][i];
for(k = i; k <= x; k ++){
martix[j][k] -= r * martix[i][k];
}
}
}
memset(ans, 0, sizeof(ans));
for(i = x - 1; i >= 0; i --){
double tmp = 0;
for(j = x - 1; j > i; j --){
tmp += martix[i][j] * ans[j];
}
ans[i] = (-martix[i][x] - tmp)/martix[i][i];
}
return ans[0];
}
void solve(){
memset(reach, false, sizeof(reach));
dfs(0);
if(!reach[n]){
printf("Impossible\n");
return ;
}
int ls = 0;
for(int i = 0; i < n; i ++){
if(reach[i]){
index[i] = ls ++;
}
}
double one = 1.0/6.0;
memset(martix, 0, sizeof(martix));
for(int i = 0; i < n; i ++){
if(!reach[i])
continue;
martix[index[i]][index[i]] = -1;
for(int j = 1; j <= 6; j ++){
int pn = getNext(i, j);
int pfn = fp[pn];
if(pfn != INF)
pn = getNext(pn, fp[pn]);
if(pn == n){
martix[index[i]][ls] += one;
}
else if(pfn == 0){
martix[index[i]][index[pn]] += one;
martix[index[i]][ls] += one*2;
}
else{
martix[index[i]][index[pn]] += one;
martix[index[i]][ls] += one;
}
}
}
printf("%.2lf\n", gauss(ls));
}
int main(){
read();
solve();
return 0;
}