天天看点

Hdu 4418 Time travel 概率DP Time travel

Time travel

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3229    Accepted Submission(s): 853

Problem Description

Hdu 4418 Time travel 概率DP Time travel

Agent K is one of the greatest agents in a secret organization called Men in Black. Once he needs to finish a mission by traveling through time with the Time machine. The Time machine can take agent K to some point (0 to n-1) on the timeline and when he gets to the end of the time line he will come back (For example, there are 4 time points, agent K will go in this way 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, ...). But when agent K gets into the Time machine he finds it has broken, which make the Time machine can't stop (Damn it!). Fortunately, the time machine may get recovery and stop for a few minutes when agent K arrives at a time point, if the time point he just arrive is his destination, he'll go and finish his mission, or the Time machine will break again. The Time machine has probability Pk% to recover after passing k time points and k can be no more than M. We guarantee the sum of Pk is 100 (Sum(Pk) (1 <= k <= M)==100). Now we know agent K will appear at the point X(D is the direction of the Time machine: 0 represents going from the start of the timeline to the end, on the contrary 1 represents going from the end. If x is the start or the end point of the time line D will be -1. Agent K want to know the expectation of the amount of the time point he need to pass before he arrive at the point Y to finish his mission.

If finishing his mission is impossible output "Impossible !" (no quotes )instead.

Input There is an integer T (T <= 20) indicating the cases you have to solve. The first line of each test case are five integers N, M, Y, X .D (0< N,M <= 100, 0 <=X ,Y < 100 ). The following M non-negative integers represent Pk in percentile.

Output For each possible scenario, output a floating number with 2 digits after decimal point

If finishing his mission is impossible output one line "Impossible !" 

(no quotes )instead.

Sample Input

2
4 2 0 1 0
50 50
4 1 0 2 1
100
        

Sample Output

8.14
2.00
        

Source 2012 ACM/ICPC Asia Regional Hangzhou Online

有一个数轴,从0到n-1.现在有一个人从x出发,每次可以随机走1~m格,走到起点、终点时自动转身。给出走1,2,...m格各自的概率,求到y的期望步数。

把数轴变为0,1,2,3,...n-1,n,n-1...1,0,这样可以认为人在一个环上走,且方向一定。

首先bfs一遍,看每个状态能否到达。

之后根据状态转移关系列出线性方程组,消元解决。

注意考虑起点和终点相同的情况。

#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=205,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const db eps=1e-6;
int dfn[maxn]; 
db r[maxn][maxn],a[maxn];
int m,num;

bool bfs(int n,int s,int t) {
	int i;num=0;
	queue<int> q; 
	q.push(s);
	memset(dfn,-1,sizeof(dfn));
	dfn[s]=num++;
	while (!q.empty()) {
		int now=q.front();
		q.pop();
		for (i=1;i<=m;i++) {
			int to=(now+i)%n; 
			if (dfn[to]==-1&&a[i]>eps) {
				dfn[to]=num++;
				q.push(to);
			}
		}
	}
	return dfn[t]!=-1||dfn[n-t]!=-1;
}

bool gauss(int size) {    
    int i,j,k;    
    for (i=0;i<size;i++) {    
        k=i;    
        for (j=i+1;j<size;j++) 
            if (fabs(r[j][i])>fabs(r[k][i])) k=j;        
        if (fabs(r[k][i])<eps) return false;
        for (j=i;j<=size;j++)   
            swap(r[k][j],r[i][j]);  
        db t=r[i][i];  
        for (j=i;j<=size;j++)   
            r[i][j]/=t;  
        for (j=0;j<size;j++) {    
            if (i==j) continue;    
            db t=r[j][i];   
            for (k=i;k<=size;k++) {    
                r[j][k]-=t*r[i][k];    
            }    
        }
    }  
    return true;  
}

int main() {
	int cas;
	scanf("%d",&cas);
	while (cas--) {
		int n,x,y,d,i,j;
		scanf("%d%d%d%d%d",&n,&m,&y,&x,&d);
		for (i=1;i<=m;i++) {
			scanf("%lf",&a[i]);
			a[i]/=100.0;
		}
		if (x==y) {
			printf("0.00\n");continue;
		}
		mem0(dfn);
		n=2*(n-1);
		if (d==1) x=n-x;
		if (!bfs(n,x,y)) {
			printf("Impossible !\n");continue;
		}
		mem0(r);
		for (i=0;i<n;i++) {
			if (dfn[i]==-1) continue;
			r[dfn[i]][dfn[i]]=1.0;
			if (i==y||i==n-y) continue;
			for (j=1;j<=m;j++) {
				if (dfn[(i+j)%n]==-1||a[j]<eps) continue;
				r[dfn[i]][dfn[(i+j)%n]]-=a[j];
				r[dfn[i]][num]+=a[j]*j;
			}
		}
		if (!gauss(num)) {
			printf("Impossible !\n");
		} else {
			printf("%.2lf\n",r[dfn[x]][num]);
		}
	}
	return 0;
}