雅礼集训 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}\)可以进行若干次以 ...
随机推荐
- Spring框架进阶3
Spring框架进阶3 测试spring_jdbc和spring对事务的管理 先配置相应的pom <?xml version="1.0" encoding="UTF ...
- udp发送广播消息
import socket if __name__ == '__main__': # 创建udpsocket udp_socket = socket.socket(socket.AF_INET, so ...
- python核心编程2 第八章 练习
8–2. 循环. 编写一个程序, 让用户输入三个数字: (f)rom, (t)o, 和 (i)ncrement . 以 i为步长, 从 f 计数到 t , 包括 f 和 t . 例如, 如果输入的是 ...
- 彻底弄懂session,cookie,token
session,cookie和token究竟是什么 简述 我在写之前看了很多篇session,cookie的文章,有的人说先有了cookie,后有了session.也有人说先有session,后有co ...
- 1016-06-首页20-封装工具条---UITableView控件距离顶部的间距问题----cell选中时的背景颜色设置
一.设置UITableView里面的顶部 cell 距离顶部的间距的三种方式: 方法 1. 直接设置: self.tableView.contentInset = UIEdgeInsetsMake(H ...
- python——集合
在python中,字典的亲戚就是集合,集合就是无映射关系的字典,花括号并不是字典的特权.如下面程序所示: >>> num = {} >>> type(num) &l ...
- Java实现Avl树
Avl树即左右子树的深度[高度]相差不可超过1,所以在插入key的时候,就会出现需要旋转[更改根节点]的操作 下面是源代码: /* the define of avltree's node */ cl ...
- HDU 6386 Age of Moyu
Problem Description Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting ...
- spark提交运算原理
前面几天元旦过high了,博客也停了一两天,哈哈,今天我们重新开始,今天我们介绍的是spark的原理 首先先说一个小贴士: spark中,对于var count = 0,如果想使count自增,我们不 ...
- PHP.28-TP框架商城应用实例-后台5-多表操作-商品表与品牌表
表与表之间的关系:1:1 1:多 多:多 功能需求决定表关系 此处的表关系为:品牌表:商品表=1:多 1.首先在表结构上关联,在多的表(商品表)添加一个字段,关联一的表(品牌表)的ID(主键) 添加字 ...