[bzoj1444]有趣的游戏

将所有字符串建一个ac自动机,用f[i]表示随机字符串匹配到第i个字符的概率,可以转移到某些字符,如果这个点是末尾那么他只能转移到自己且概率为1,高斯消元即可
(另外还有一个有趣的做法,因为精度要求不高,可以直接对这个矩阵自乘50次得到的就是结果)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 105
 4 queue<int>q;
 5 int V,n,l,m,x,y,end[N],vis[N],nex[N],ch[N][N];
 6 double p[N],f[N][N];
 7 char s[N];
 8 void add(char *s,int p){
 9     int k=1;
10     for(int i=0;s[i];i++){
11         if (!ch[k][s[i]-‘A‘])ch[k][s[i]-‘A‘]=++V;
12         k=ch[k][s[i]-‘A‘];
13     }
14     vis[k]=1;
15     end[p]=k;
16 }
17 void build(){
18     for(int i=1;i<=V;i++)nex[i]=1;
19     for(int i=0;i<m;i++)
20         if (ch[1][i])q.push(ch[1][i]);
21     while (!q.empty()){
22         int k=q.front();
23         q.pop();
24         vis[k]|=vis[nex[k]];
25         for(int i=0;i<m;i++)
26             if (!ch[k][i])ch[k][i]=ch[nex[k]][i];
27             else{
28                 nex[ch[k][i]]=ch[nex[k]][i];
29                 q.push(ch[k][i]);
30             }
31     }
32 }
33 void guess(){
34     for(int i=1;i<=V;i++){
35         double s=fabs(f[i][i]);
36         for(int j=i+1;j<=V;j++)s=max(s,fabs(f[j][i]));
37         for(int j=i;j<=V;j++)
38             if (s==fabs(f[j][i])){
39                 s=f[j][i];
40                 for(int k=i;k<=V+1;k++)swap(f[i][k],f[j][k]);
41                 break;
42             }
43         for(int j=i;j<=V+1;j++)f[i][j]/=s;
44         for(int j=1;j<=V;j++)
45             if (i!=j){
46                 s=f[j][i];
47                 for(int k=i;k<=V+1;k++)f[j][k]-=f[i][k]*s;
48             }
49     }
50 }
51 int main(){
52     scanf("%d%d%d",&n,&l,&m);
53     for(int i=0;i<m;i++){
54         scanf("%d%d",&x,&y);
55         p[i]=1.0*x/y;
56     }
57     V=1;
58     for(int i=1;i<=n;i++){
59         scanf("%s",s);
60         add(s,i);
61     }
62     build();
63     for(int i=1;i<=V;i++)
64         for(int j=0;j<m;j++)
65             if (!vis[i])f[ch[i][j]][i]+=p[j];
66     for(int i=1;i<=V;i++)f[i][i]--;
67     f[1][V+1]=-1;
68     guess();
69     for(int i=1;i<=n;i++)printf("%.2f\n",f[end[i]][V+1]);
70 }

原文地址:https://www.cnblogs.com/PYWBKTDA/p/11742548.html

时间: 2024-08-25 14:51:03

[bzoj1444]有趣的游戏的相关文章

bzoj1444 有趣的游戏(AC自动机+概率dp)

题意: 给定n个长度为l的模式串,现在要用前m个大写字母生成一个随机串,每个字符有自己的出现几率,第一次出现的字符串获胜,求最终每个字符串的获胜几率. 分析: 容易想到先把所有的字符串建成一个AC自动机 然后对于生成的随机串就相当于从AC自动机的root开始在自动机上走,然后求走到每个单词节点的概率 因为这是存在环的,不是DAG图,所以不能直接DP 考虑构造出刚开始的转移矩阵,然后对转移矩阵作矩阵乘法不断迭代就能得到正确答案了 转移矩阵如何建呢? 1)a[i][ch[i][j]]+=p[j] (

【BZOJ1444】[Jsoi2009]有趣的游戏 AC自动机+概率DP+矩阵乘法

[BZOJ1444][Jsoi2009]有趣的游戏 Description Input 注意 是0<=P Output Sample Input Sample Output HINT  30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10. 题解:本题的做法真的很多啊,概率DP,期望DP,当然还有矩乘黑科技~ 就是先跑AC自动机,弄出转移矩阵,然后自乘50次就行了. #include <cstdio> #include <

Nim Game,一个有趣的游戏,也是一道入门算法题。

Nim Game,其实很多人都玩过.其实就是我们玩的划线游戏. 一张纸上,画若干条线,双方一人划一次,每次划掉1~3条线.可以选择画1条,也可以划2条,也可以3条.具体划去几条线完全看自己的策略.谁划掉最后一条线,就是赢家. 如上图,蓝方获胜. 正在看这篇文章的你一定是一个聪明人,每一步都是最优解,而你的对手,也跟你一样聪明,每步都是最优的解法. 现在你作为先手,在线条总数为多少的时候,你必赢呢,又在多少的时候必输呢? 可不可以用一个函数来判断在线条总是为x时你的输赢情况呢?这样你以后跟别人玩这

java编程的一个猜数字有趣小游戏

import javax.swing.Icon; import javax.swing.JOptionPane; public class ai { /** * @param args */ public static void main(String[] args) { Icon icon = null; boolean bl = false; int put = 0; int c = (int) (((Math.random())*100)+1); //获取一个1-100的随机数 Syste

110种有趣的游戏和应用

声明:这是一篇译文,查看原文请猛戳http://www.datamation.com/open-source/110-fun-open-source-games-and-apps-1.html. 又一次,我们庆祝夏天的到来,和夏天一同来到的还有一系列开源的高品质游戏.今年的最佳游戏列表在去年的基础上,增加了一些好玩的游戏,同时删除了一些不再处于活跃开发状态的游戏.在这个列表中,你会发现街机类游戏,棋盘类游戏,休闲类游戏,益智类游戏,教育类游戏,第一人称射击类游戏,音乐类游戏,跑酷类游戏,角色扮演

BZOJ1444 : [Jsoi2009]有趣的游戏

建立AC自动机,并求出转移矩阵. 再用$\sum E(终止节点)=1$去替换第一个方程,高斯消元即可. 时间复杂度$O(n^3l^3)$. 注意精度问题,要特判0.00的情况. #include<cstdio> #include<cmath> #include<algorithm> #define N 110 using namespace std; int n,l,S,i,j,k,tot,son[N][10],v[N],fail[N],q[N],fin[N]; cha

有趣的游戏:Google XSS Game

Google最近出了一XSS游戏: https://xss-game.appspot.com/ 我这个菜鸟看提示,花了两三个小时才全过了.. 这个游戏的规则是仅仅要在攻击网页上弹出alert窗体就能够了. 题目页面是在iframe里嵌套的展现的.那么父窗体是怎样知道iframe里成功弹出了窗体? 是这样子实现的: 题目页面载入了这个js,改写了alert函数,当alert被调用时,向parent发送一个消息. https://xss-game.appspot.com/static/game-fr

Android用SurfaceView写一个简单有趣的游戏--《数字组合》之一

最近突然有了一个想法--做一款android的简单游戏练练手,既要实现起来简单(毕竟只有一个人,框架什么的暂且就不用考虑了),又要能够达到对android知识框架的复习和游戏要有可玩性,终于用了几个星期写完了.和大家分享分享体会吧. 本来打算写一个专栏的.看以后的时间吧. 首先介绍一下游戏的主要思想和SurfaceView也就是游戏主界面的代码分享,后续部分再更新吧. 在点击 开始游戏 后,进行组合数字的选择,根据难易程度系统默认选择2和8,选择界面中间显示选择的组合数字,第一个数字表示第一个组

BZOJ 1444 JSOI2009 有趣的游戏 AC自动机+矩阵乘法

题目大意:给定n个长度为l的模式串,现在要用前m个大写字母生成一个随机串,每个字符有自己的出现几率,第一次出现的字符串获胜,求最终每个字符串的获胜几率 建出AC自动机,搞出转移矩阵 如果某个节点是模式串那么这个节点只向自己连一条概率为1的出边 然后把转移矩阵自乘50遍即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 120 us