zoukankan      html  css  js  c++  java
  • hdu4418(概率dp + 高斯消元)

    应该是一个入门级别的题目。

    但是有几个坑点。

    1. 只选择x能到达的点作为guass中的未知数。

    2. m可能大于n,所以在构建方程组时未知数的系数不能直接等于,要+=

    3.题意貌似说的有问题,D为-1的时候,和题目说的不一样.

    //
    //  main.cpp
    //  hdu4418
    //
    //  Created by New_Life on 16/8/9.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    //高斯消元模板:  浮点数
    
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #define maxn 210
    #define N 210
    #define CL(a,num) memset((a),(num),sizeof(a))
    #define iabs(x)  ((x) > 0 ? (x) : -(x))
    #define EPS 1e-8
    using namespace std;
    int equ,var;//方程个数和自由元的个数
    double a[maxn][maxn];
    double x[maxn],free_x[maxn];//解集
    
    void Debug()
    {
        int i,j;
        for(i=0;i<equ;i++){
            for(j=0;j<var+1;j++)
                printf("%.2lf ",a[i][j]);
            cout<<endl;
        }
    }
    
    int zero(double x)
    {
        if( iabs(x)<EPS ) return 1;
        return 0;
    }
    int Guass(){
        int i,j,k,col;
        CL(x,0);CL(free_x,1);//清空解集
        
        for(k=0,col=0;k<equ && col<var ;k++,col++){//枚举行和列
            //	cout<<k<<" "<<col<<endl;
            int max_r = k;
            for(i=k+1;i<equ;i++)
                if(iabs(a[i][col]) > iabs(a[max_r][col])) max_r = i;
            if(max_r != k)//交换
                for(i=k;i<var+1;i++)
                    swap(a[k][i],a[max_r][i]);
            
            if( zero(a[k][col]) ) {
                k--; //为什么有k--;模拟下这样可以减的多点
                continue;
            }
            
            for(i=k+1;i<equ;i++){
                if(!zero(a[i][col])){
                    //	int lcm = LCM(a[k][col],a[i][col]);
                    //	int ta = lcm/iabs(a[i][col]);
                    //	int tb = lcm/iabs(a[k][col]);
                    //	如果读入的矩阵是整数可按照上面的写,否则得按照下面的写
                    double tb = iabs(a[i][col])/iabs(a[k][col]);
                    if(a[i][col]*a[k][col]<0) tb=-tb;
                    for(j=col;j<var+1;j++)
                        a[i][j] = a[i][j] - tb*a[k][j];
                }
            }
        }
        //	Debug();
        //1.无解的情况出现(0,0,0,0,……a)这样的行且a!=0
        for(i=k;i<equ;i++){
            if(!zero(a[i][col]))
            {
                printf("Impossible !
    ");
                return -1;
            }
        }
        //2.无穷解的情况,再var*(var+1)的增广矩阵中出现(0,0,0……0)这样的行
        //出现的行数便是自由变元的个数
        if(k<var){
            int num = 0,freeidx=0;
            for(i=k-1;i>=0;i--){
                num=0;
                //用于判断该行的不确定的变元的个数,如果超过1则无法求解
                //它们仍然为不确定的变元
                double tmp = a[i][var];
                for(j=0;j<var;j++)
                    if(!zero(a[i][j]) && free_x[j]){
                        num++;
                        freeidx = j;
                    }
                if(num>1) continue;
                tmp=a[i][var];
                for(j=0;j<var;j++){
                    if(!zero(a[i][j]) && j != freeidx) tmp -= a[i][j]*x[j];
                }
                x[freeidx] = tmp/a[i][freeidx];
                free_x[freeidx]=0;
            }
            if(free_x[0] == 0) printf("%.2lf
    ",x[0]);
            else printf("Impossible !
    ");
            return var-k;
        }
        //3.唯一解的情况
        for(i=k-1;i>=0;i--)
        {
            double tmp=a[i][var]*1.0;
            for(j=i+1;j<var;j++)
                tmp-=a[i][j]*x[j];
            x[i] = tmp/(a[i][i]*1.0);
        }
        printf("%.2lf
    ",x[0]);
        return 0;
    }
    
    double g[N];
    int tg[N];
    int mark[N][2];
    int id = 0;
    int n,m;
    double savevar[N];
    int flagflag;
    
    //感觉这里面可以直接建立方程
    void dfs(int p,int d,int y)
    {
        int td = d;
        mark[p][d] = id++;
        int tp = p;
        a[ mark[p][d] ][ mark[p][d] ] = -1;
        double tmp = 0;
        for(int i=1;i<=m;i++)
        {
            if(d==0) tp++;
            else tp--;
            
            if(tp == 0) d = 0;
            else if(tp==n-1) d=1;
            
            if(tg[i]==0) continue;
            
            tmp += i*g[i];
            
            if(tp==y) {flagflag=1;continue;}
            
            if(mark[tp][d]==-1)
                dfs(tp,d,y);
            
            a[ mark[p][td] ][ mark[tp][d] ] += g[i];//这里确实有点问题
        }
        savevar[ mark[p][td] ] = tmp;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            flagflag = 0;
            int y,p,d;
            cin>>n>>m>>y>>p>>d;
            memset(savevar,0,sizeof(savevar));//真是神奇的错误啊
            for(int i=1;i<=m;i++)
            {
                int tmp;
                scanf("%d",&tmp);
                tg[i] = tmp;
                g[i] = (double)tmp/100;
            }
            if(y==p)
            {
                printf("0.00
    ");
                continue;
            }
            memset(mark,-1,sizeof(mark));
    //        if(d==-1)
    //        {
    //            if(p==0) d = 0;
    //            else d = 1;
    //        }
            if(p==0) d=0;
            else if(p==n-1) d=1;
            id = 0;
            memset(a,0,sizeof(a));
            dfs(p,d,y);
    //        if(flagflag == 0)
    //        {
    //            printf("Impossible !
    ");
    //            continue;
    //        }
            for(int i=0;i<id;i++)//有id个等式
            {
                a[i][id] = -savevar[i];
            }
            equ = var = id;
    //        for(i=0;i<equ;i++)
    //            for(j=0;j<var+1;j++){
    //                scanf("%lf",&a[i][j]);
    //            }
            //Debug();
            //cout<<endl;
            int free_num=Guass();
    //        co++;
    //        printf("Case #%d:",co);
    //        if(free_num==0)
    //        {
    //            printf("%.2lf",(iabs(x[0])<EPS?EPS:x[0]));
    //            for(int i=1;i<var;i++) printf(" %.2lf",(iabs(x[i])<EPS?EPS:x[i]));
    //            cout<<endl;
    //        }else cout<<"Can't solve it."<<endl;
            //无求无穷多解的情况
        }
        return 0;
    }
    
    /*
     100
     4 2 0 1 0
     0 100
     4 10 0 1 0
     10 10 5 5 0 20 20 20 2 8
     10 5 5 0 -1
     10 20 30 20 20
     10 100 5 9 -1
     1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
     10 4 1 2 0
     0 20 0 80
     100 4 1 2 0
     0 20 0 80
     100 100 5 9 0
     1 1 1 1 1 1 1 1 1 1 0 1 1 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
     100 4 1 2 0
     0 20 1 79
     */
    

      

  • 相关阅读:
    Oracle基础知识整理
    linux下yum安装redis以及使用
    mybatis 学习四 源码分析 mybatis如何执行的一条sql
    mybatis 学习三 mapper xml 配置信息
    mybatis 学习二 conf xml 配置信息
    mybatis 学习一 总体概述
    oracle sql 语句 示例
    jdbc 新认识
    eclipse tomcat 无法加载导入的web项目,There are no resources that can be added or removed from the server. .
    一些常用算法(持续更新)
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5754902.html
Copyright © 2011-2022 走看看