ZOJ 3560 Re: the Princess 高斯消元
2014-03-27 10:36
225 查看
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25040
题意:一开始女王发了一个帖,然后很多人跟帖,问发帖数的期望。(才发现是princess是公主
)
解法:首先是字符串处理出g[i][j],表示第j个人的nickname在第i个人的signatures中出现的次数,in[i]表示出了i之外所有人的nickname在i的signatures出现的次数。那么i发了帖之后j跟帖的概率是a[i][j] = 1.0 * g[i][j] / in[i]. 那么整个发帖就可以想像成一个有向图,从i点走向j点的概率是a[i][j],没有路之后停止,问走过的点数的期望。
可以列出方程:
dp[1] = a[1][2] * dp[2] + a[1][3] * dp[3] + a[1][4] * dp[4] + ... + a[1]
* dp[1]
+ 1;
dp[2] = a[2][1] * dp[1] + a[2][3] * dp[3] + a[2][4] * dp[4] + ...+ a[2]
* dp[2]
+ 1;
.......................
可以列出n个方程,一共有n个未知数。果断就是高斯消元解方程了:
重点我想说的是这个样例:
3
princess: x
a: b
b: a
很多人ac的代码输出的是inf的,我觉得根据题意应该是输出1的。我的代码加了50到54行来把和女王不相关的点去掉:
题意:一开始女王发了一个帖,然后很多人跟帖,问发帖数的期望。(才发现是princess是公主
)
解法:首先是字符串处理出g[i][j],表示第j个人的nickname在第i个人的signatures中出现的次数,in[i]表示出了i之外所有人的nickname在i的signatures出现的次数。那么i发了帖之后j跟帖的概率是a[i][j] = 1.0 * g[i][j] / in[i]. 那么整个发帖就可以想像成一个有向图,从i点走向j点的概率是a[i][j],没有路之后停止,问走过的点数的期望。
可以列出方程:
dp[1] = a[1][2] * dp[2] + a[1][3] * dp[3] + a[1][4] * dp[4] + ... + a[1]
* dp[1]
+ 1;
dp[2] = a[2][1] * dp[1] + a[2][3] * dp[3] + a[2][4] * dp[4] + ...+ a[2]
* dp[2]
+ 1;
.......................
可以列出n个方程,一共有n个未知数。果断就是高斯消元解方程了:
#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<algorithm> using namespace std; #define M 1200 #define N 110 const double eps = 1e-8; int dcmp( double x ) { return ( x > eps ) - ( x < -eps ); } char name[110][20], sign[110][M]; char str[M]; int n; int find( char *str, char *s ) { int ans = 0; for( int i = 0; str[i]; ++i ){ int k = 0; while( str[i+k] && s[k] && str[i+k] == s[k] ) ++k; if( !s[k] ){ if( str[i+k] >= 'a' && str[i+k] <= 'z' ) continue; if( i && str[i-1] >= 'a' && str[i-1] <= 'z' ) continue; ++ans; } } return ans; } int vis ; double a ; int g , in ; void dfs( int u ) { vis[u] = 1; for( int i = 1; i <= n; ++i ) if( !vis[i] && g[u][i] ) dfs( i ); } double solve() { memset( a, 0, sizeof(a) ); for( int i = 1; i <= n; ++i ){ a[i][i] = a[i][n+1] = -1; for( int j = 1; j <= n; ++j ) if( g[i][j] ) a[i][j] = 1.0 * g[i][j] / in[i]; } memset( vis, 0, sizeof(vis) ); dfs( 1 ); for( int i = 1; i <= n; ++i ) if( !vis[i] ){ for( int j = 1; j <= n + 1; ++j ) a[i][j] = 0; a[i][i] = 1; } int k, row = 1, col = 1; double x; while( row <= n && col <= n ){ k = row; while( k <= n && !dcmp( a[k][col] ) ) ++k; if( k > n ){ ++col; continue; } if( k - row ) for( int j = col; j <= n+1; ++j ) swap( a[k][j], a[row][j] ); for( int i = 1; i <= n; ++i ) if( i - row ){ x = a[i][col] / a[row][col]; for( int j = col; j <= n + 1; ++j ) a[i][j] -= x * a[row][j]; } ++row, ++col; } k = row; while( k <= n ){ if( dcmp( a[k][n+1] ) ) return -1; ++k; } if( !dcmp( a[1][1] ) ) return -1; return a[1][n+1] / a[1][1]; } int main() { //freopen( "a.in", "r", stdin ); while( scanf( "%d", &n ) == 1 ){ getchar(); for( int i = 1; i <= n; ++i ){ gets( str ); int j = 0, k = 0; while( str[j] != ':' ) name[i][j] = str[j], ++j; name[i][j] = '\0'; ++j; while( str[j] ) sign[i][k++] = str[j++]; sign[i][k] = '\0'; } memset( in, 0, sizeof(in) ); memset( g, 0, sizeof(g) ); int c; for( int i = 1; i <= n; ++i ) for( int j = 1; j <= n; ++j ) if( i - j ){ if( c = find( sign[i], name[j] ) ) g[i][j] = c, in[i] += c; } double ans = solve(); if( ans < 0 ) printf( "Infinity\n" ); else printf( "%.3lf\n", ans ); } }
重点我想说的是这个样例:
3
princess: x
a: b
b: a
很多人ac的代码输出的是inf的,我觉得根据题意应该是输出1的。我的代码加了50到54行来把和女王不相关的点去掉:
memset( vis, 0, sizeof(vis) ); dfs( 1 ); for( int i = 1; i <= n; ++i ) if( !vis[i] ){ for( int j = 1; j <= n + 1; ++j ) a[i][j] = 0; a[i][i] = 1; }
相关文章推荐
- ZOJ 3645 BiliBili(高斯消元)
- ZOJ 3645 (简单的高斯消元)
- ZOJ 3645 (高斯消元)
- 高斯消元 zoj 3645 poj 1222/XOR消元
- zoj 3645 高斯消元
- zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数
- ZOJ 3353 Chess Board && NEFU OJ 506(高斯消元好题)
- NEFU 506&&ZOJ 3353 Chess Board (四种构造的高斯消元)
- ZOJ - 2619 Generator 高斯消元
- ZOJ 3645 BiliBili 高斯消元 难度:1
- zoj 2619 KMP+高斯消元+概率求期望
- ZOJ-3645 BiliBili(高斯消元)
- UVALive 3490 (LA 3940) || ZOJ 2619 Generator AC自动机(或KMP) + 整数高斯消元 + 数学期望
- ZOJ 3645 :BiliBili _高斯消元
- zoj 3353 Chess Board(高斯消元)
- zoj 3353 Chess Board 高斯消元
- BiliBili zoj 3645 (高斯消元,数学)
- ZOJ 3645 BiliBili (高斯消元)
- BZOJ 3143 游走(高斯消元)
- HDU 4326 Game(概率DP+高斯消元)