HDU 5966 Guessing the Dice Roll

题意
有 N≤10 个人,每个猜一个长度为L≤10的由1?6构成的序列,保证序列两两不同。
不断地掷骰子,直到后缀与某人的序列匹配,则对应的人获胜。
求每个人获胜的概率。

思路:
建立trie图,跑高斯消元.
高斯消元每个点的意义是:
第i行第j列的值为x 有概率x从点j转移过来

  1 const double eps = 1e-9;
  2 const int SIGMA_SIZE = 7;
  3 const int MAXNODE = 200;
  4
  5 int ch[MAXNODE][SIGMA_SIZE];
  6 int f[MAXNODE];
  7 int sz;
  8
  9 void insert(int* P, int len, int v) {
 10     int u = 0;
 11     for (int i = 0; i < len; i++) {
 12         int c = P[i];
 13         if (!ch[u][c]) {
 14             memset(ch[sz], 0, sizeof(ch[sz]));
 15             ch[u][c] = sz++;
 16         }
 17         u = ch[u][c];
 18     }
 19 }
 20
 21 void getFail() {
 22     f[0] = 0;
 23     queue<int> q;
 24     for (int c = 1; c < SIGMA_SIZE; c++) {
 25         int u = ch[0][c];
 26         if (u) {
 27             q.push(u);
 28             f[u] = 0;
 29         }
 30     }
 31     while (!q.empty()) {
 32         int r = q.front(); q.pop();
 33         for (int c = 1; c < SIGMA_SIZE; c++) {
 34             int u = ch[r][c];
 35             if (!u) {
 36                 ch[r][c] = ch[f[r]][c];
 37                 continue;
 38             }
 39             q.push(u);
 40             int v = f[r];
 41             while (v && !ch[v][c]) v = f[v];
 42             f[u] = ch[v][c];
 43         }
 44     }
 45 }
 46
 47 //double的高斯消元
 48 double a[MAXNODE][MAXNODE], x[MAXNODE];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果
 49 int equ, var;//方程数和未知数个数
 50 int Gauss()
 51 {
 52     for (int k=0, col=0; k<equ && col<var; k++, col++)
 53     {
 54         int max_r=k;
 55         for (int i=k+1; i<equ; i++)
 56             if (fabs(a[i][col]) > fabs(a[max_r][col])) max_r=i;
 57         if (fabs(a[max_r][col]) < eps) return 0;
 58         if (k != max_r)
 59         {
 60             for (int j = col; j < var; j++) swap(a[k][j], a[max_r][j]);
 61             swap(x[k], x[max_r]);
 62         }
 63         x[k] /= a[k][col];
 64         for (int j=col+1; j<var; j++) a[k][j] /= a[k][col];
 65         a[k][col] = 1;
 66         for (int i=0; i<equ; i++)
 67             if (i != k)
 68             {
 69                 x[i] -= x[k] * a[i][k];
 70                 for(int j=col+1; j<var; j++) a[i][j]-=a[k][j]*a[i][col];
 71                 a[i][col] = 0;
 72             }
 73     }
 74     return 1;
 75 }
 76
 77 const int maxn = 20;
 78 int n, len;
 79 int peo[maxn][maxn];
 80 bool end[MAXNODE];
 81 vector<int> G[MAXNODE];
 82
 83 void init()
 84 {
 85     memset(f, 0, sizeof(f));
 86     memset(ch, 0, sizeof(ch));
 87     memset(a, 0, sizeof(a));
 88     memset(end, 0, sizeof(end));
 89     memset(x, 0, sizeof(x));
 90
 91     sz = 1;
 92     scanf("%d%d", &n, &len);
 93     for (int i = 1; i <= n; i++)
 94     {
 95         for (int j = 0; j < len; j++)
 96         {
 97             scanf("%d", &peo[i][j]);
 98         }
 99         insert(peo[i], len, i);
100         end[sz - 1] = true;
101     }
102     for (int i = 0; i < sz; i++)
103     {
104         G[i].clear();
105     }
106 }
107
108 void getGraph()
109 {
110     getFail();
111     for (int i = 0; i < sz; i++)
112     {
113         if (!end[i])
114         {
115             for (int j = 1; j < 7; j++)
116             {
117                 int t = ch[i][j];
118                 G[t].push_back(i);
119             }
120         }
121     }
122 }
123
124 void solve()
125 {
126     getGraph();
127     equ = var = sz;
128     for (int i = 0; i <sz; i++)
129     {
130         for (auto j : G[i])
131         {
132             a[i][j] += 1.0/6;
133         }
134         a[i][i] -= 1;
135     }
136     x[0] = -1;
137
138     Gauss();
139
140     vector<double> ans;
141     for (int i = 0; i < sz; i++)
142     {
143         if (end[i])
144         {
145             ans.push_back(x[i]);
146         }
147     }
148     for (int i = 0; i < ans.size() - 1; i++)
149     {
150         printf("%.6f ", ans[i]);
151     }
152     printf("%.6f\n", *ans.rbegin());
153
154 }
155
156 int main()
157 {
158     int T;
159     scanf("%d", &T);
160     while (T--)
161     {
162         init();
163         solve();
164     }
165     return 0;
166 }
时间: 2024-08-06 15:42:27

HDU 5966 Guessing the Dice Roll的相关文章

hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】

hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机,求匹配到终止结点的概率,用 高斯消元?一开始不知道怎么建方程组,直接举个例子吧: Input: 1 2 2 1 1 2 1 图解: x0原本概率就是1,然后还要加上其他结点走向它的概率,,这样最后算下来是大于1的,现在还是觉得怪怪的... 1 #include <cstdio> 2 #inclu

hdu 5995 Guessing the Dice Roll(AC自动机+矩阵)

题目链接:hdu 5995 Guessing the Dice Roll 题意: 有一个6面的骰子,有n(n≤10)个人每个人猜了一个长度为l(l≤10)的序列,不停的掷骰子直到满足一个人的序列则那个人获胜,求每个人获胜的概率. 题解: 将他们猜的串插入AC自动机,然后转移k次,这里k要足够大才能收敛,然后因为总节点数最多才60个,所以用矩阵来加速. 正解应该是用高斯消元来做这个事情. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,

hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】【待补...】

2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1632    Accepted Submission(s): 480 Problem Description There are N

【AC自动机】【高斯消元】hdu5955 Guessing the Dice Roll

http://blog.csdn.net/viphong/article/details/53098489 我有一点不是很懂,这样算出来转移到AC自动机根节点的概率是一个远大于1的数. 按我的理解,因为转移初始就是从根节点出发的, 所以x(0)存储的是从根节点出发的概率(100%)+其他点转移到根节点的概率-- 比较抽象,还是当做套路记住吧--(鶸的做法) #include<cstdio> #include<cstring> #include<cmath> #inclu

Hdu 4386 Play the Dice 解题报告

hdu 4586---Play the dice 解题思路:概率 题目描述:一个骰子有n面,每面朝上的概率相同,并且每一面上面都有一个数字,其中有m面是彩色的,代表掷到彩色面的时还可以继续掷下去,问最终掷得的数字的期望是多少? 解题方法: 方法一:只考虑单独掷每一次的情况,可以发现,每次掷到的期望是和先前无关的,假设a=sum/n(每掷一次的期望都是a),比如:掷第一次的时候期望是a,掷第二次的时候期望便是(m/n)*a,因为有(m/n)的概率能够掷第二次..依次可以继续下去,等比求和即可. u

HDU 4586 Play the Dice(概率+期望)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4586 Problem Description There is a dice with n sides, which are numbered from 1,2,...,n and have the equal possibility to show up when one rolls a dice. Each side has an integer ai on it. Now here is a

hdu 4586 Play the Dice (概率+等比数列)

Play the Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1328    Accepted Submission(s): 429 Special Judge Problem Description There is a dice with n sides, which are numbered from 1,2,...

HDU 4586 Play the dice(概率题,推公式)

Problem Description: There is a dice with n sides, which are numbered from 1,2,...,n and have the equal possibility to show up when one rolls a dice. Each side has an integer ai on it. Now here is a game that you can roll this dice once, if the i-th

LeetCode 1223. Dice Roll Simulation

原题链接在这里:https://leetcode.com/problems/dice-roll-simulation/ 题目: A die simulator generates a random number from 1 to 6 for each roll. You introduced a constraint to the generator such that it cannot roll the number i more than rollMax[i] (1-indexed) c