noip2016考了一道状压dp,一道期望dp

然而这题是状压期望dp...

所以难度是什么,省选noi吗...

怎么办...

题目大意:

给定n个字符串,甲从中任选出一个串(即选出每个串的概率相同为1/n),乙要通过询问甲选出的字符串pos位置上的字符是什么来确定这个串。然而由于有些字符串的一些位置上字符相同,所以可能不能通过一次询问达成目标。现在乙没有任何策略地进行随机询问,问乙能够确定答案的询问次数期望是多少?

其中n<=50,每个字符串长度相等且长度<=20

题解:

首先状压是比较好想的,但是和期望结合起来了,我们怎么办呢?

那么我们先尝试对询问进行状压,这也是最显然的一个思路:记1表示该位置已被询问过,0表示该位置未被询问过。

那么我们考虑转移:设状态为dp[i],字符串长度为l,那么dp[i]+=dp[i|(1<<j)]*1/tot

看懵了?

首先我们要知道,这是个期望dp,状态表示的是已经问了i状态的问题,距离得到想要的字符串的期望距离是多少

于是显然我们从后向前更新。

接下来,我们设j是i状态中没问过的一个问题,那么dp[i]就可以由dp[i|(1<<j)]转移过来

而设i状态中没问过的问题数为tot,那么问出问题j的概率就是1/tot

但...你有没有觉得缺点什么?

是啊,这样根本忽略掉了字符串,变成了无论你读入什么串结果都一样,因为转移中根本没体现出字符串的存在!!!

所以这个转移显然是并不完全的。

那么我们要考虑一下完善它

我们维护另一个数组s,用s[i]表示问i状态的问题有多少字符串是彼此区分不开的

然后在转移dp时,我们使用这个方程:dp[i]=(∑dp[i|(1<<j)]*1/tot*num[i|(1<<j)]/num[i])+1

这样就比较完善了。

至于证明:前半部分不说了,我们就说一下后面除法的部分:

其实这个方程可玄学了,网上其他方程都和这个不一样,但这是最简洁的一个...

稍微证明一下,就是说当状态为i时,待确定的串有num[i]个,而当状态为(1<<j)|i时,待确定的状态有num[(1<<j)|i]个

这样一来,无法确定所求串的概率就是num[(1<<j)|i]/num[i],所以乘上这个概率就好了。

至于num数组如何维护,首先我们记录某一状态i下有哪些串不能确定,那么如果询问为i的子集这些串显然也不能确定,那么我们再把所有的子集查出来维护一下就好了。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
int num[(1<<20)+5];
double dp[(1<<20)+5];
ll unusage[(1<<20)+5];
int n,l;
char ch[55][25];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",ch[i]);
}
if(n==1)
{
printf("0.000000000\n");
return 0;
}
l=strlen(ch[1]);
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
ll sit=0;
for(int k=0;k<l;k++)
{
if(ch[i][k]==ch[j][k])
{
sit|=(1ll<<k);
}
}
unusage[sit]|=(1ll<<i);
unusage[sit]|=(1ll<<j);
}
}
for(int i=(1<<l)-1;i>=1;i--)
{
for(int j=0;j<l;j++)
{
if(i&(1<<j))
{
unusage[i^(1<<j)]|=unusage[i];
}
}
}
for(int i=0;i<(1<<l);i++)
{
for(int j=0;j<n;j++)
{
if(unusage[i]&(1ll<<j))
{
num[i]++;
}
}
}
dp[(1<<l)-1]=0;
for(int i=(1<<l)-2;i>=0;i--)
{
if(!num[i])
{
dp[i]=0;
continue;
}else
{
int tot=l;
for(int j=0;j<l;j++)
{
if((1<<j)&i)
{
tot--;
}
}
for(int j=0;j<l;j++)
{
if((1<<j)&i)
{
continue;
}
dp[i]+=dp[i|(1<<j)]*1.0/(double)(tot)*(double)(num[i|(1<<j)])/(double)(num[i]);
}
dp[i]+=1.0;
}
}
printf("%.9lf\n",dp[0]);
return 0;
}

2018.8.1 状压 CF482C 题解的更多相关文章

  1. UOJ426. 【集训队作业2018】石像 [状压DP,min_25筛]

    UOJ 思路 (以下思路是口胡,但正确性大概没有问题.) 刚学min_25筛的时候被麦老大劝来做这题? 结果发现这题是个垃圾二合一?? 简单推一下式子可以得到答案就是这个: \[ \sum_{T=1} ...

  2. DP练习(概率,树状,状压)

    http://vjudge.net/contest/view.action?cid=51211#overview 花了好长时间了,终于把这个专题做了绝大部分了 A:HDU 3853 最简单的概率DP求 ...

  3. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  4. POJ 3254 - Corn Fields - [状压DP水题]

    题目链接:http://poj.org/problem?id=3254 Time Limit: 2000MS Memory Limit: 65536K Description Farmer John ...

  5. bzoj3195 [Jxoi2012]奇怪的道路——状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3195 看到数据范围就应该想到状压呢... 题解(原来是这样):https://www.cnb ...

  6. noi省选 [九省联考2018]一双木棋题解(状压dp)

    比浙江简单多了........ 题目转送:https://www.luogu.org/problemnew/show/P4363 分析: 我们注意到n和m都很小,考虑一下状压dp. 显然,棋子摆成的形 ...

  7. bzoj 2669 题解(状压dp+搜索+容斥原理)

    这题太难了...看了30篇题解才整明白到底咋回事... 核心思想:状压dp+搜索+容斥 首先我们分析一下,对于一个4*7的棋盘,低点的个数至多只有8个(可以数一数) 这样的话,我们可以进行一个状压,把 ...

  8. [BZOJ5248] 2018九省联考 D1T1 一双木棋 | 博弈论 状压DP

    题面 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子 ...

  9. POJ - 3254 Corn Fields(状压DP)题解

    思路: 参照blog,用状压DP做,和题解稍微有点不一样,我这里直接储存了状态而不是索引. 这一题的问题是怎么判断相邻不能种,我们用2进制来表示每一行的种植情况.我们将每一行所能够造的所有可能都打表( ...

随机推荐

  1. JAVA进阶1

    间歇性混吃等死,持续性踌躇满志系列-------------第1天 1.冒泡排序法 import java.util.Arrays; public class SumNum{ public stati ...

  2. VMware 11安装Mac和Linux

    VMware 11安装Mac OS X 10.10_百度经验 https://jingyan.baidu.com/article/ff411625b9011212e48237b4.html?qq-pf ...

  3. JAVA知识笔记

    1.对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的.更详细介绍参考http://blog.csdn.net/libing13820393394/articl ...

  4. kali linux 安装 matlab2016Rb

    分享安装包: https://pan.baidu.com/s/1hrBd3Li 密码:u9q3 由于Linux版的分为两个镜像,需要挂载后合并: mount R2016b_glnxa64_dvd1.i ...

  5. 虚拟机安装CentOS配置静态IP

    在VMware中安装Linux虚拟机后(比如CentOS6.*),不能访问网络,需要配置静态IP.虚拟机中推荐使用NET模式进行网络连接,在虚拟机的工具栏点击编辑>虚拟网络编辑器>NET模 ...

  6. JavaScript-DOM(重点)

    解析过程 DOM树(一切皆是节点) DOM可以做什么 清楚DOM的结构 获取其它DOM(事件源)的三种方式 事件 事件的三要素 绑定事件的方式 JavaScript入口函数 window.onload ...

  7. 设计模式C++学习笔记之二十(完结篇 & 面向对象原则)设计模式C++实例下载

      Prototype(原型模式) 20.1.解释 概念:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. main(),客户 ICloneableNow,只有一个接口Clone CM ...

  8. SharePoint 2013 错误 0x800700DF 文件大小超出允许的限制,无法保存

    问题描述: 利用资源管理员往SharePoint 2013文档库里复制文件时,报错了. 错误 0x800700DF︰ 文件大小超过了允许的限制,无法保存. 解决方法: 解决方法,可以修改本地电脑注册表 ...

  9. hibernate框架学习第二天:核心API、工具类、事务、查询、方言、主键生成策略等

    核心API Configuration 描述的是一个封装所有配置信息的对象 1.加载hibernate.properties(非主流,早期) Configuration conf = new Conf ...

  10. 用Cordova打包Vue-vux项目

    技术搭建:vue + vux 首先推荐阅读这篇文章,写的已经很详细了:https://www.jianshu.com/p/25d797b983cd 此处记录下我按照这篇文章打包的时候报的一些错误,方便 ...