zoukankan      html  css  js  c++  java
  • HDU 4418 高斯消元法求概率DP

    把两种状态化成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
    ",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
    ", x[has[s]]);
    	}
        return 0;
    }
    

      

  • 相关阅读:
    11.14 mii-tool:管理网络接口的状态
    11.15 dmidecode:查询系统硬件信息
    11.11 ntsysv:管理开机服务
    HDU 2476 String painter 刷字符串(区间DP)
    HDU 1085 Holding Bin-Laden Captive! 活捉本拉登(普通型母函数)
    母函数的应用
    HDU 1028 Ignatius and the Princess III伊格和公主III(AC代码)母函数
    HDU 1059 Dividing 分配(多重背包,母函数)
    HDU 2955 Robberies抢劫案(01背包,变形)
    HDU 1011 Starship Troopers星河战队(树形dp)
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4120226.html
Copyright © 2011-2022 走看看