bzoj 2337 高斯消元+概率DP

  题目大意:

每条路径上有一个距离值,从1走到N可以得到一个所有经过路径的异或和,求这个异或和的数学期望

这道题直接去求数学期望的DP会导致很难列出多元方程组

我们可以考虑每一个二进制位从1走到N的平均概率值

因为整个图是联通的那么所有点都默认会处于多元方程组中

Pi = p[i] * sigma( v&d[i][j]?(1-Pj):Pj)

v是当前二进制位代表的数值

这里需要注意的是自环的加边情况,自环只加一次边,不能向平时那样加无向边一样

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 using namespace std;
  8 const int N = 205;
  9 const int M = 10005;
 10 #define eps 1e-8
 11 int first[N] , k , degree[N] , n , m;
 12 double p[N] , a[N][N];
 13
 14 void debug()
 15 {
 16     for(int i=0 ; i<n ; i++){
 17         for(int j=0 ; j<=n ; j++)
 18             cout<<a[i][j]<<" ";
 19         cout<<endl;
 20     }
 21 }
 22
 23 struct Edge{
 24     int y , next , d;
 25     Edge(int y=0 , int next=0 , int d=0):y(y),next(next),d(d){}
 26 }e[M<<1];
 27
 28 void add_edge(int x,int y,int d)
 29 {
 30     e[k] = Edge(y , first[x] , d);
 31     first[x] = k++;
 32 }
 33
 34 int get_width(int x)
 35 {
 36     int ret =0 ;
 37     while(x)
 38     {
 39         x>>=1;
 40         ret++;
 41     }
 42     return ret;
 43 }
 44
 45 void build(int v)
 46 {
 47     memset(a , 0 , sizeof(a));
 48     for(int i=0 ; i<n ; i++){
 49         a[i][i] = 1;
 50         if(i==n-1) continue;
 51         for(int j=first[i] ; ~j ; j=e[j].next){
 52             int u = e[j].y;
 53             if(v&e[j].d){
 54                 a[i][u] += p[i];
 55                 a[i][n] += p[i];
 56             }else{
 57                 a[i][u] -= p[i];
 58             }
 59         }
 60     }
 61    // debug();
 62 }
 63
 64 int gauss(int n)
 65 {
 66     int i,j,k;
 67     for(i=0 , j=0 ; i<n&&j<n ; j++){
 68         for(k=i ; k<n ; k++)
 69             if(fabs(a[k][j])>eps) break;
 70         if(k<n){
 71             if(i!=k)
 72                 for(int r=j ; r<=n ; r++) swap(a[i][r],a[k][r]);
 73             double tt = 1.0/a[i][j];
 74             for(int r=j ; r<=n ; r++) a[i][r] *= tt;
 75             for(int r=0 ; r<n ; r++){
 76                 if(r == i) continue;
 77                 for(int t=n ; t>=j ; t--)
 78                     a[r][t] -= a[i][t]*a[r][j];
 79             }
 80             i++;
 81         }
 82     }
 83     for(int r=i ; r<n ; r++)
 84         if(fabs(a[r][n])>eps) return 0;
 85     return 1;
 86 }
 87
 88 int main()
 89 {
 90     #ifndef ONLINE_JUDGE
 91         freopen("a.in" , "r" , stdin);
 92     #endif // ONLINE_JUDGE
 93     while(~scanf("%d%d" , &n , &m))
 94     {
 95         memset(first , -1 , sizeof(first));
 96         memset(degree , 0 , sizeof(degree));
 97         k = 0;
 98         int maxn = 0;
 99         for(int i=0 ; i<m ; i++){
100             int x,y,d;
101             scanf("%d%d%d" , &x , &y , &d);
102             add_edge(x-1,y-1,d);
103             if(x!=y){
104                 add_edge(y-1 , x-1 , d);
105                 degree[x-1]++ , degree[y-1]++;
106             }
107             else degree[x-1]++;
108             maxn = max(maxn , d);
109         }
110         for(int i=0 ; i<n ; i++) p[i] = 1.0/(degree[i]*1.0);//得到从当前点每条边出发的概率
111         int len = get_width(maxn);
112         double ret= 0;
113         for(int i=0 ; i<len ; i++){
114             int v = 1<<i;
115             build(v);
116             gauss(n);
117             ret += v*a[0][n];
118         }
119         printf("%.3f\n" , ret);
120     }
121     return 0;
122 }
时间: 2024-10-04 14:29:37

bzoj 2337 高斯消元+概率DP的相关文章

UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP

题目来源:UVa 10828 Back to Kernighan-Ritchie 题意:从1开始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每个点的期望 思路:写出方程消元 方程有唯一解 多解 无解的情况 有环 一直再环里无法停止算无穷大 从1不能到的点期望为0 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <

hdu4870 Rating (高斯消元或者dp)

Rating Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 213 Accepted Submission(s): 126 Special Judge Problem Description A little girl loves programming competition very much. Recently, she has f

【BZOJ-3143】游走 高斯消元 + 概率期望

3143: [Hnoi2013]游走 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2264  Solved: 987[Submit][Status][Discuss] Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数

bzoj 1013 高斯消元

将二维求圆心的方式推广到n维,然后用高斯消元解. 具体来说就是,设圆上的两点A(a1,a2,...,an), B(b1,b2,...,bn) 和 圆心C(c1,c2,...,cn),则 ∑(ai-ci)2 = ∑(bi-ci)2 ∑2*(ai-bi)*ci=∑(ai2-bi2) 总共有n+1个点,有C(n+1,2)个方程,但很多是冗余的,可以用一个点与其它n个点建立上述方程,然后解出来.

【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径

2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 682  Solved: 384[Submit][Status][Discuss] Description 几乎是一路看题解过来了.. 拖了一个星期的题目- - 已然不会概率DP(说得好像什么时候会过一样),高斯消元(打一次copy一遍). 发现异或题目的新解决方法:按位处理.. 发现DP新方法:高斯消元. f[k][i]代表第k位权值起点为i到终点时答案

【BZOJ 2337】 2337: [HNOI2011]XOR和路径(概率DP、高斯消元)

2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1170  Solved: 683 Description Input Output Sample Input Sample Output HINT Source Day2 [分析] 这题终于自己打出来了高斯消元.没有对比代码了... 很心酸啊..调试的时候是完全没有方向的,高斯消元还要自己一步步列式子然后消元解..[为什么错都不知道有时候 这题显然是不能

bzoj 2337 [HNOI2011]XOR和路径【高斯消元+dp】

首先,我们发现,因为是无向图,所以相连的点之间是有"依赖性"的,所以不能直接用dp求解. 因为是xor,所以按位处理,于是列线性方程组,设$ x[i] $为点i到n异或和为1的期望,因为从1到n和从n到1一样,所以选择倒着推,即, if(deg[e[i].va]==0) \[ x[u]=\sum_{v}^{v\subset son(u)}\frac{x[v]}{deg[i]} \] else \[ x[u]=\sum_{v}^{v\subset son(u)}\frac{1-x[v])

【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元

题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两个不同端点A_j和B_j (1 <= A_j<= N; 1 <= B_j <= N)表示的双向道路连接.保证城市1至少连接一个其它的城市.一开始臭气弹会被放在城市1.每个小时(包括第一个小时),它有P/Q (1 <= P <=1,000,000; 1 <= Q <

【BZOJ3640】JC的小苹果 概率DP+高斯消元

[BZOJ3640]JC的小苹果 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话说JC历经艰辛来到了城市B,但是由于他的疏忽DZY偷走了他的小苹果!没有小苹果怎么听歌!他发现邪恶的DZY把他的小苹果藏在了一个迷宫里.JC在经历了之前的战斗后他还剩下hp点血.开始JC在1号点,他的小苹果在N号点.DZY在一些点里放了怪兽.当JC每次遇到位置在i的怪兽时他会损失Ai点血.当JC的血小于等于0时他就会被自动弹出迷