雅礼集训 Day3 T2 v 解题报告
v
题目背景
\(\frac 14\)遇到了一道水题,又完全不会做,于是去请教小\(\text{D}\)。小\(\text{D}\)看了\(0.607\)眼就切掉了这题,嘲讽了\(\frac 14\)一番就离开了。
于是,\(\frac 14\)只好来问你,这道题是这样的:
题目描述
有\(n\)个球排成一行,每个球的颜色为黑或白。
执行\(k\)次操作,第\(i(1\le i\le k)\)次操作形式如下:
• 从\([1,n-i+1]\)中,等概率随机选择一个整数\(x\)。
• 移除从左往右数的第\(x\)个球,或从右往左数的第\(x\)个球(也就是从左往右数的第\(n-i+2-x\)个)。之后,所有右侧的球的编号减\(1\)。
给定每个球的颜色信息,希望最大化移除的白球数量。
输出在最优策略下,期望的移除白球数量。误差在\(10^{-6}\)范围内,即算正确。
输入输出格式
输出格式
从文件v.in
中读入数据。
第一行,两个整数\(n,k\)。
第二行,一个长度为\(n\)、仅由'W'
和'B'
组成的字符串,第\(i\)个字符代表第\(i\)个球的颜色,'W'
为白色,'B'
为黑色。
输入格式
输出到文件v.out
中。
输出一行,一个浮点数,代表答案。
说明
数据范围
保证\(1\le n\le 30\),\(0\le k\le n\)。
\(\text{Subtask}\) | 分值 | \(n\le\) | 其他限制 |
---|---|---|---|
\(1\) | \(20\) | \(5\) | 无 |
\(2\) | \(25\) | \(20\) | 无 |
\(3\) | \(1\) | \(30\) | 保证\(k=0\)或\(k=n\) |
\(4\) | \(1\) | \(30\) | 保证字符串所有字符相同 |
\(5\) | \(19\) | \(30\) | 保证字符串只有一个'W' |
\(6\) | \(19\) | \(30\) | 保证字符串只有一个'B' |
\(7\) | \(15\) | \(30\) | 无 |
挂了一堆部分分。。。惨无人道啊。
45pts状压一下
\(dp_{i,sta}=\sum max(dp_{i-1,to1},dp_{i-1,to2})\)
因为要倒着做所以直接记搜就行了
剩下的部分分瞎搞一下
100pts就是把状态存储小的用数组存,大的用map...
我太菜而最后一个点实在是卡不过去了
Code:
#include <cstdio>
#include <cstring>
#include <map>
int n,k;
std::map <int,double> dp[31];
double dp0[24][1<<23];
char s[32];
double max(double x,double y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
double dfs(int sta,int siz)
{
if(siz==n-k) return 0;
if(siz>23&&dp[siz].find(sta)!=dp[siz].end()) return dp[siz][sta];
if(siz<=23&&dp0[siz][sta]!=-1.0) return dp0[siz][sta];
double sum=0;
for(int i=1;i<=siz>>1;i++)
{
int co1=sta>>i-1&1,co2=sta>>siz-i&1;
int to1=sta>>1&~((1<<i-1)-1)|sta&(1<<i-1)-1;
int to2=sta>>1&~((1<<siz-i)-1)|sta&((1<<siz-i)-1);
sum+=2*max(dfs(to1,siz-1)+co1,dfs(to2,siz-1)+co2);
}
if(siz&1)
{
int i=siz+1>>1;
int to=sta>>1&~((1<<i-1)-1)|sta&(1<<i-1)-1;
int co=sta>>i-1&1;
sum+=dfs(to,siz-1)+co;
}
sum=sum/siz;
return siz>23?dp[siz][sta]=sum:dp0[siz][sta]=sum;
}
int main()
{
scanf("%d%d%s",&n,&k,s);
int st=0;
for(int i=n-k+1;i<=min(23,n);i++)
for(int j=0;j<1<<i;j++)
dp0[i][j]=-1.0;
for(int i=1;i<=n;i++)
st|=(s[i-1]=='W')<<n-i;
printf("%.8lf\n",dfs(st,n));
return 0;
}
2018.10.3
UPT on 2018.10.12:我卡过去了,并且学会了一个小技巧
发现状态数组实际上有很多浪费,因为每个\(i\)的状态都是\(2^i\)的,我们没必要开两维
直接开一维\(dp_{sta}\)就可以。
但是这样可能造成重复之类的,我们可以给某一个长度为\(i\)的维度把\(i+1\)位打1标记,代表这是第\(i\)维的
这是很常见的一个技巧了
Code:
// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <map>
int n,k;
std::map <int,double> dp;
double dp0[1<<25];
char s[32];
double max(double x,double y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
double dfs(int sta,int siz)
{
if(siz==n-k) return 0;
if(siz>24&&dp.find(sta)!=dp.end()) return dp[sta];
if(siz<=24&&dp0[sta]!=-1.0) return dp0[sta];
double sum=0;
for(int i=1;i<=siz>>1;i++)
{
int co1=sta>>i-1&1,co2=sta>>siz-i&1;
int to1=sta>>1&~((1<<i-1)-1)|sta&(1<<i-1)-1;
int to2=sta>>1&~((1<<siz-i)-1)|sta&((1<<siz-i)-1);
sum+=2.0*max(dfs(to1,siz-1)+co1,dfs(to2,siz-1)+co2)/siz;
}
if(siz&1)
{
int i=siz+1>>1;
int to=sta>>1&~((1<<i-1)-1)|sta&(1<<i-1)-1;
int co=sta>>i-1&1;
sum+=(dfs(to,siz-1)+co)/siz;
}
return siz>24?dp[sta]=sum:dp0[sta]=sum;
}
int main()
{
scanf("%d%d%s",&n,&k,s);
int st=0;
for(int i=0;i<1<<25;i++)
dp0[i]=-1.0;
for(int i=1;i<=n;i++)
st|=(s[i-1]=='W')<<n-i;
st|=1<<n;
printf("%.8lf\n",dfs(st,n));
return 0;
}
雅礼集训 Day3 T2 v 解题报告的更多相关文章
- 雅礼集训 Day3 T2 u 解题报告
u 题目背景 \(\frac 14\) 遇到了一道水题,完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了一眼就切掉了这题,嘲讽了\(\frac 14\)一番就离开了. ...
- 雅礼集训 Day3 T3 w 解题报告
w 题目背景 \(\frac 14\)遇到了一道水题,双完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了\(0.607^2\)眼就切掉了这题,嘲讽了\(\frac 14 ...
- 雅礼集训 Day6 T2 Equation 解题报告
Equation 题目描述 有一棵\(n\)个点的以\(1\)为根的树,以及\(n\)个整数变量\(x_i\).树上\(i\)的父亲是\(f_i\),每条边\((i,f_i)\)有一个权值\(w_i\ ...
- 「雅礼集训 2017 Day2」解题报告
「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...
- 「雅礼集训 2017 Day1」 解题报告
「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...
- 雅礼集训 Day1 T3 画作 解题报告
画作 题目描述 小\(\mathrm{G}\)的喜欢作画,尤其喜欢仅使用黑白两色作画. 画作可以抽象成一个\(r\times c\)大小的\(01\)矩阵.现在小\(\mathrm{G}\)构思好了他 ...
- 雅礼集训 Day5 T3 题 解题报告
题 题目背景 由于出题人赶时间所以没办法编故事来作为背景. 题目描述 一开始有\(n\)个苹果,\(m\)个人依次来吃苹果,第\(i\)个人会尝试吃\(u_i\)或\(v_i\)号苹果,具体来说分三种 ...
- 雅礼集训 Day2 T3 联盟 解题报告
联盟 题目描述 \(\text{G}\) 国周边的 \(n\) 个小国家构成一个联盟以抵御 \(\text{G}\) 国入侵, 为互相支援,他们建立了\(n−1\) 条双向通路, 使得任意两个国家可以 ...
- 雅礼集训 Day7 T1 Equation 解题报告
Reverse 题目背景 小\(\text{G}\)有一个长度为\(n\)的\(01\)串\(T\),其中只有\(T_S=1\),其余位置都是\(0\).现在小\(\text{G}\)可以进行若干次以 ...
随机推荐
- docker快速安装jenkins
用过docker的人,可能真的很难忍受再一步步二进制安装了,好了话不多说,感慨一下jenkins实现自动化发布构建真的很方便. 推荐一个学习的好地方https://m.w3cschool.cn/jen ...
- 01U盘PE系统制作方法
1. 需要的工具和安装包:WinPE镜像文件 WinPE_x86.iso .已制作好的另一个启动盘(下文以映像总裁为例,当然也可以使用大白菜.U启动等) . 电脑.准备制作PE系统的空U盘 2. 还原 ...
- webpack最小化lodash
lodash作为一个比较常用的前端开发工具集,在使用webpack进行vendor分离的实践中,会遇到将整个lodash文件分离到vendor.js的问题.这样会使vendor.js文件变得特别大. ...
- Python学习笔记:PEP8常用编程规范
PEP8编码规范是一种非常优秀的编码规范,也得到了Python程序员的普遍认可,如果实践中或者项目中没有统一的编码规范,建议尽量遵循PEP8编码规范,当然如果项目中已经有了自身的编码规范,应当优先遵循 ...
- strak组件(5):为列表定制预留钩子方法
效果图: 新增函数 def get_list_display(self): 获取页面上应该显示的列,预留的自定义扩展,例如:以后根据用户的不同显示不同的 一.stark组件 stark/servic ...
- 虚拟机linux桥接联网问题
Linux系统为redhat5.8 虚拟机的版本:vm8.0 本人刚刚开始接触linux,今日需要通过linux进行联网,因此也学习了一点点关于虚拟机的联网的知识,在此与大家进行分享,希望大家可以之处 ...
- Hive LanguageManual DDL
hive语法规则LanguageManual DDL SQL DML 和 DDL 数据操作语言 (DML) 和 数据定义语言 (DDL) 一.数据库 增删改都在文档里说得也很明白,不重复造车轮 二.表 ...
- [Jenkins]持续集成环境下fingbug插件的安装使用与配置
参考:https://wiki.jenkins.io/display/JENKINS/FindBugs+Plugin 突然,天降杂事.我是想安安静静的做个美丽的测试...但是事与愿违,项目经理叫我帮忙 ...
- jsUnpacker
EVAL function executeEval(){ let evalCodeElt = document.getElementById("eval_code"); let e ...
- gettid 和pthread_self的区别
转: Linux中,每个进程有一个pid,类型pid_t,由getpid()取得.Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库 ...