HDU 5966 Guessing the Dice Roll

Posted 我好懒啊!(┬_┬)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于HDU 5966 Guessing the Dice Roll的主要内容,如果未能解决你的问题,请参考以下文章

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

E. XOR Guessing(Meet in the Middle)

CF1486 C2. Guessing the Greatest (hard version)

CodeForces - 1486C2 Guessing the Greatest (hard version)(二分+交互)

HDOJ5955Guessing the Dice Roll(概率DP,AC自动机,高斯消元)

LeetCode #389. Find the Difference