1. 程式人生 > >lightoj 1151 概率dp + 高斯消元

lightoj 1151 概率dp + 高斯消元

連結:vjudge..

題意:10*10的地圖,不過可以直接看成1*100的,從1出發,要到達100,每次走的步數用一個完美的大小為6的骰子決定。地圖上有A和B,A和B都使你跳躍,不過一個是往前跳,一個是使你往後跳。。問從1走到100的期望

思路:概率dp的方程很簡單就能想到,不過由於可以往前或者往後走,沒法直接遞推,用高斯消元解方程組得到解。//原來一直都懶得用高斯消元,都想遞推解決,不過有些題目用高斯消元確實簡單,雖然時間會比遞推多

程式碼://高斯消元中的無解或者多個解的部分對這道題沒有用處,註釋掉的solve是輸入輸出的例子

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

///高斯消元模板
const double eps = 1e-7;    ///精度
const int Max_M = 110;       ///m個方程,n個變數
const int Max_N = 110;
int m, n;
double Aug[Max_M][Max_N+1]; ///增廣矩陣
bool free_x[Max_N];         ///判斷是否是不確定的變元
double x[Max_N];            ///解集
double fx[110];///記錄f(x)

int sign(double x){ return (x>eps) - (x<-eps);}
int Gauss(){
    int row,col,max_r;
    for(row=0,col=0; row<m&&col<n; row++,col++){
        max_r = row;
        for(int i = row+1; i < m; i++){///找到當前列所有行中的最大值(做除法時減小誤差)
            if(sign(fabs(Aug[i][col]) - fabs(Aug[max_r][col])) > 0)
                max_r = i;
        }
        if(max_r != row){///將該行與當前行交換
            for(int j = row; j < n+1; j++)
                swap(Aug[max_r][j],Aug[row][j]);
        }
        if(sign(Aug[row][col])==0){///當前列row行以下全為0(包括row行)
            row--;
            continue;
        }
        for(int i = row+1; i < m; i++){
            if(sign(Aug[i][col])==0)
                continue;
            double ta = Aug[i][col]/Aug[row][col];
            for(int j = col; j < n+1; j++)
                Aug[i][j] -= Aug[row][j]*ta;
        }
    }
    ///無解或者多個解的情況
    for(int i = row; i < m; i++){
        if(sign(Aug[i][col]))
            return -1;///col=n存在0...0,a的情況,無解
    }
    if(row < n){
        for(int i = row-1; i >=0; i--){
            int free_num = 0;   ///自由變元的個數
            int free_index;     ///自由變元的序號
            for(int j = 0; j < n; j++){
                if(sign(Aug[i][j])!=0 && free_x[j])
                    free_num++,free_index=j;
            }
            if(free_num > 1) continue;  ///該行中的不確定的變元的個數超過1個,無法求解,它們仍然為不確定的變元
            ///只有一個不確定的變元free_index,可以求解出該變元,且該變元是確定的
            double tmp = Aug[i][n];
            for(int j = 0; j < n; j++){
                if(sign(Aug[i][j])!=0 && j!=free_index)
                    tmp -= Aug[i][j]*x[j];
            }
            x[free_index] = tmp/Aug[i][free_index];
            free_x[free_index] = false;
        }
        return n-row;///存在0...0,0的情況,有多個解,自由變元個數為n-row個
    }
    ///無解或者多個解的情況
    for(int i = n-1; i >= 0; i--){
        double tmp = Aug[i][n];
        for(int j = i+1; j < n; j++)
            if(sign(Aug[i][j])!=0)
                tmp -= Aug[i][j]*x[j];
        x[i] = tmp/Aug[i][i];
    }
    return 0;///有且僅有一個解,嚴格的上三角矩陣(n==m)
}
/**
返回值:
-1 無解
0 有且僅有一個解
>=1 有多個解,根據free_x判斷哪些是不確定的解
**/

/*void solve(){
    cin>>m>>n;///m個方程,n個變數
    memset(Aug,0.0,sizeof(Aug));///矩陣陣列
    memset(x,0,sizeof(x));///最終的解的陣列
    memset(free_x,1,sizeof(free_x));///判斷是否為不確定的變元
    for(int i = 0;i < m;i ++){
        for(int j = 0;j < n;j ++){
            cin>>Aug[i][j];///輸入矩陣
        }
    }
    for(int i = 0;i < m;i ++){
        cin>>Aug[i][n];///輸入解
    }

    int ans = Gauss();///高斯消元,返回ans代表各種型別的解
    for(int i = 0;i < n;i ++){///輸出解
        cout<<x[i]<<endl;
    }
}*/

bool ff[110];
int main()
{
    //freopen("in.txt","r",stdin);
    //solve();
    int T;
    int cas = 1;
    cin>>T;
    n = m = 100;
    while(T --){
        memset(Aug,0.0,sizeof(Aug));
        memset(x,0.0,sizeof(x));
        memset(free_x,1,sizeof(free_x));
        memset(ff,0,sizeof(ff));
        int t;
        cin>>t;
        while(t --){
            int a,b;
            cin>>a>>b;
            ff[a] = 1;
            Aug[a-1][a-1] = 1.0;
            Aug[a-1][b-1] = -1.0;
            Aug[a-1][100] = 0;
        }
        for(int i = 1;i <= 100;i ++){
            if(ff[i] == 0){
                if(i + 6 <= 100){
                    Aug[i-1][i-1] = 1;
                    for(int j = 1;j <= 6;j ++){
                        Aug[i-1][i-1 + j] = -(1.0/6.0);
                    }
                    Aug[i-1][100] = 1;
                }
                else {
                    Aug[i-1][i-1] = 1.0 - (i*1.0 - 94)/6.0;
                    int all = 100 - i;
                    for(int j = 1;j <= all;j ++){
                        Aug[i-1][i-1 + j] = -(1.0/6.0);
                    }
                    Aug[i-1][100] = 1.0;
                }
            }
        }
        Aug[99][99] = 1;Aug[99][100] = 0;
        int a = Gauss();//cout<<a<<endl;
        double ans = x[0];
        printf("Case %d: %.8f\n",cas ++,ans);
    }
    return 0;
}


相關推薦

LightOJ - 1151概率dp+

include 得到 ofa 期望 cas efi cos size com 概率dp+高斯消元 https://vjudge.net/problem/LightOJ-1151 題意:剛開始在1,要走到100,每次走的距離1-6,超過100重來,有一些點可能有傳送點,可

lightoj 1151 概率dp +

連結:vjudge.. 題意:10*10的地圖,不過可以直接看成1*100的,從1出發,要到達100,每次走的步數用一個完美的大小為6的骰子決定。地圖上有A和B,A和B都使你跳躍,不過一個是往前跳,一個是使你往後跳。。問從1走到100的期望 思路:概率dp的方程很簡單就能想

【BZOJ3640】JC的小蘋果 概率DP+

找到 100% strong bsp struct == 自動彈出 pre ems 【BZOJ3640】JC的小蘋果 Description 讓我們繼續JC和DZY的故事。 “你是我的小丫小蘋果,怎麽愛你都不嫌多!”

BZOJ2337 [HNOI2011]XOR和路徑 【概率dp +

但是 ++ clu alt HA exit rep 等於 找到 題目 題解 突然get到這樣路徑期望的題目八成是高斯消元 因為路徑上的dp往往具有後效性,這就形成了一個方程組 對於本題來說,直接對權值dp很難找到突破口 但是由於異或是位獨立的,我們考慮求出每一位的期望 設

[BZOJ5292][BJOI2018]治療之雨(概率DP+)

out 個數 nbsp get tar else scanf 處理 scan https://blog.csdn.net/xyz32768/article/details/83217209 不難找到DP方程與輔助DP方程,發現DP方程具有後效性,於是高斯消元即可。 但樸

【BZOJ3143】[Hnoi2013]遊走 期望DP+

結束 strong 思路 add tin clu long family continue 【BZOJ3143】[Hnoi2013]遊走 Description 一個無向連通圖,頂點從1編號到N,邊從1編號到M。 小Z在該圖上進行隨機遊走,初始時小Z在1號頂點,每一

【bzoj3143】[Hnoi2013]遊走 期望dp+

接下來 map 頂點 log ++ double ans fabs limits 題目描述 一個無向連通圖,頂點從1編號到N,邊從1編號到M。 小Z在該圖上進行隨機遊走,初始時小Z在1號頂點,每一步小Z以相等的概率隨機選 擇當前頂點的某條邊,沿著這條邊走到下一個頂點,獲得

bzoj 3143 [Hnoi2013]遊走 期望dp+

ace 保留 sca earch algorithm 整數 include 上進 連通 [Hnoi2013]遊走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3394 Solved: 1493[Submit][St

hdu4418 Time travel 【期望dp +

mes char print puts || algo har return ssi 題目鏈接 BZOJ4418 題解 題意:從一個序列上某一點開始沿一個方向走,走到頭返回,每次走的步長各有概率,問走到一點的期望步數,或者無解 我們先將序列倍長形成循環序列,\(n =

luoguP3232 [HNOI2013]遊走 貪心 + 概率期望 +

調試 print 不知道 pri read 復雜度 計算 limits 結束 首先,題目中的無向簡單連通圖代表著沒有自環,重邊... 總分的期望 = 每條邊的期望之和...................每條邊的期望又可以拆成$u \to v$的期望和$v \to u

BZOJ4820 SDOI2017硬幣遊戲(概率期望++kmp)

  容易想到的做法是建出AC自動機,高斯消元。然而自動機上節點數量是nm的。   注意到我們要求的變數只有n個,考慮將其他不用求的節點合併為一個變數。這個變數即表示隨機生成一個串,其不包含任何一個模板串的概率。   現在即有n+1個變數,考慮列出n+1個方程。設pi表示第i個人勝利的概率,顯然有Σpi=1

2018.09.23 bzoj3143: [Hnoi2013]遊走(dp+

傳送門 顯然只需要求出所有邊被經過的期望次數,然後貪心把邊權小的邊定城大的編號。 所以如何求出所有邊被經過的期望次數? 顯然這隻跟邊連線的兩個點有關。 於是我們只需要求出兩個點被經過的期望次數。 對於一

【題解】codeforces24D Broken robot 期望DP+

題目連結 Description You received as a gift a very clever robot walking on a rectangular board. Unfortunately, you understood that it i

[BZOJ5292][Bjoi2018]治療之雨(期望DP+

Address Solution 首先,一個顯然的 DP 狀態: f[i]f[i]f[i] 表示第一個數當前為 iii ,將其變成 000 的期望步數。 邊界當然是 f[0]=0f[0]=0f[0]=0 。 討論一波轉移: 設 P(i,x)P(i,x)P(i,

[HNOI2011]XOR和路徑 概率期望

xor gist ace get swa == head 處理 std 題解:因為異或不太好處理,,,因此按位來算,這樣最後的答案就是每一位上的值乘對應的權值再求和。本著期望要倒退的原則,,,我們設$f[i]$表示從$i$到$n$,xor和為1的概率。那麽觀察$xor

bzoj 2337 [HNOI2011]XOR和路徑【+dp

name 直接 ring size scanf 高斯消元 str pre hnoi 首先,我們發現,因為是無向圖,所以相連的點之間是有“依賴性”的,所以不能直接用dp求解。 因為是xor,所以按位處理,於是列線性方程組,設$ x[i] $為點i到n異或和為1的期望,因為從1

bzoj 3143 [Hnoi2013]遊走【+dp

sca source include hnoi2013 esp cst cpp std ans 參考:http://blog.csdn.net/vmurder/article/details/44542575 和2337有點像 設點u的經過期望(還是概率啊我也分不清,以下都

bzoj 2337 [HNOI2011]XOR和路徑 +期望dp

return set 時間復雜度 += memset als \n line sum 題面 題目傳送門 解法 既然有異或,那麽我們把每一位單獨考慮一下 先枚舉是二進制的第幾位,然後設\(f_i\)表示點\(i\)這一位為1的概率是多少 顯然,可以列出一個方程 註意,自環的出

[BZOJ2337][HNOI2011]XOR和路徑(概率+)

直接不容易算,考慮拆成位處理。 設f[i]表示i到n的期望路徑異或和(僅考慮某一位),則$f[y]=\sum\limits_{exist\ x1\to y=0}\frac{f[x1]}{d[x1]}+\sum\limits_{exist\ x2\to y=1}\frac{1-f[x2]}{d[x2]}$。

hdu5955 Guessing the Dice Roll【AC自動機】【】【概率】【待補...】

inpu ont recommend match ble 北大 problem ng2 bottom 2016沈陽區域賽http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Li