bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】
2024-09-30 15:58:22
https://blog.sengxian.com/solutions/bzoj-1444 orz
一直是我想错了,建出AC自动机之后,实际上这个定义是设f[i]为经过i节点的 * 期望次数 * ,因为单词末尾节点走到意味着游戏结束,所以经过单词末尾节点的概率就是经过单词末尾节点的期望次数。为什么是期望呢,因为概率的上限是1,不能随便转移
这样定义状态之后,得到dp转移为
\[f[i]=\sum_{pr节点可以通过字符c转移到i节点}p[c]*f[pr]
\]
\]
因为是期望,所以root节点右边要加1
然后移项做高斯消元即可
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
const int N=105;
int n,l,m,c[N][15],tot=1,fa[N],va[N],fl,id[N];
double p[N],a[N][N],d[N];
char s[N];
void gaosi(int n)
{
for(int i=1;i<=n;i++)
{
int nw=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[nw][i])<fabs(a[j][i]))
nw=j;
for(int j=i;j<=n+1;j++)
swap(a[nw][j],a[i][j]);
for(int j=i+1;j<=n+1;j++)
a[i][j]/=a[i][i];
a[i][i]=1;
for(int j=i+1;j<=n;j++)
{
for(int k=i+1;k<=n+1;k++)
a[j][k]-=a[j][i]*a[i][k];
a[j][i]=0;
}
}
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
a[i][n+1]-=a[j][n+1]*a[i][j];
}
int main()
{
scanf("%d%d%d",&n,&l,&m);
for(int i=0,x,y;i<m;i++)
{
scanf("%d%d",&x,&y);
p[i]=(double)x/(double)y;
}
for(int ca=1;ca<=n;ca++)
{
scanf("%s",s+1);
int nw=1,f=0;
for(int i=1;i<=strlen(s+1);i++)
{
if(p[s[i]-'A']<1e-8)
f=1;
if(!c[nw][s[i]-'A'])
c[nw][s[i]-'A']=++tot;
nw=c[nw][s[i]-'A'];
}
va[nw]=1;
id[ca]=tot;//cerr<<id[ca]<<endl;
fl+=f;
}
if(fl==n)
{
for(int i=1;i<=n;i++)
puts("0.00");
return 0;
}
queue<int>q;
for(int i=0;i<m;i++)
if(c[1][i])
fa[c[1][i]]=1,q.push(c[1][i]);
else
c[1][i]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<m;i++)
if(c[u][i])
fa[c[u][i]]=c[fa[u]][i],q.push(c[u][i]);
else
c[u][i]=c[fa[u]][i];
}
a[1][1]=-1,a[1][tot+1]=-1;
for(int i=1;i<=tot;i++)
{
if(i>1)
a[i][i]--;
if(va[i])
continue;
for(int j=0;j<m;j++)
a[c[i][j]][i]+=p[j];
}//cerr<<tot<<endl;
gaosi(tot);
// for(int i=1;i<=tot;i++)
// {
// for(int j=1;j<=tot+1;j++)
// cerr<<a[i][j]<<" ";
// cerr<<endl;
// }
for(int i=1;i<=n;i++)
printf("%.2f\n",a[id[i]][tot+1]/a[id[i]][id[i]]);
return 0;
}
最新文章
- 每天一点Android干货-Activity的生命周期
- oracle基础备份和还原
- 使用openssl实现ECDSA签名以及验证功能(附完整测试源码)
- Web 前端开发人员和设计师必读文章推荐【系列二十八】
- HTML5 Canvas rect()和strokeRect() 的区别
- Multi-Device Hybrid Apps for Visual Studio CTP2.0
- boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。
- HDU 1815 Building roads
- Struts2验证
- UWP锁、解屏后无法响应操作
- Statistical Models and Social Science
- 移动端Touch事件基础
- Windows上最大传输单元MTU值的查看和设置
- string用法总结
- JAVA之字符串
- PMP:9.项目资源管理
- linux硬件数据
- SpringMVC简单项目配置
- BT656与BT1120的区别
- Color the ball(hdu1556)(hash)或(线段树,区间更新)
热门文章
- Back弹出AlertDialog
- PAT (Advanced Level) 1036. Boys vs Girls (25)
- <;项目>;<;day12>;通讯录(自己做的)
- 【纯净版windows系统】U盘启动制作图文教程
- CSS布局之BFC和IFC
- firedac数据集的序列和还原
- Making User-Managed Backups-17.3、Making User-Managed Backups of Offline Tablespaces and Datafiles
- 每天复习Shell—ls
- Codeforces Round #310 (Div. 1) C. Case of Chocolate (线段树)
- su: /bin/bash: Permission denied带来的疑惑