• 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
    ", *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 }
  • 相关阅读:
    苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)
    使用tcpdump抓取HTTP包
    android保持在休眠时,后台程序继续运行(让程序获取设备电源锁)
    insert数据时,获取插入数据的id
    Android学习笔记(五五):通知Notification(下)
    apk反编译与android项目代码混淆
    android 解决横竖屏切换时重新载入的问题
    android中往字符串数组动态添加元素
    error 25015安装程序集“C:WindowsMicrosoft .NETFrameworkv2.0.50727xxx.dll”失败,原因是出现了系统错误:另一个程序正在使用此文件,进程无法访问
    win7 安装vs2013后无法连接远程数据库,出现如下提示的解决方法
  • 原文地址:https://www.cnblogs.com/liangyongrui/p/6044921.html
Copyright © 2020-2023  润新知