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 解题报告的更多相关文章

  1. 雅礼集训 Day3 T2 u 解题报告

    u 题目背景 \(\frac 14\) 遇到了一道水题,完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了一眼就切掉了这题,嘲讽了\(\frac 14\)一番就离开了. ...

  2. 雅礼集训 Day3 T3 w 解题报告

    w 题目背景 \(\frac 14\)遇到了一道水题,双完全不会做,于是去请教小\(\text{D}\).小\(\text{D}\)看了\(0.607^2\)眼就切掉了这题,嘲讽了\(\frac 14 ...

  3. 雅礼集训 Day6 T2 Equation 解题报告

    Equation 题目描述 有一棵\(n\)个点的以\(1\)为根的树,以及\(n\)个整数变量\(x_i\).树上\(i\)的父亲是\(f_i\),每条边\((i,f_i)\)有一个权值\(w_i\ ...

  4. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  5. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

  6. 雅礼集训 Day1 T3 画作 解题报告

    画作 题目描述 小\(\mathrm{G}\)的喜欢作画,尤其喜欢仅使用黑白两色作画. 画作可以抽象成一个\(r\times c\)大小的\(01\)矩阵.现在小\(\mathrm{G}\)构思好了他 ...

  7. 雅礼集训 Day5 T3 题 解题报告

    题 题目背景 由于出题人赶时间所以没办法编故事来作为背景. 题目描述 一开始有\(n\)个苹果,\(m\)个人依次来吃苹果,第\(i\)个人会尝试吃\(u_i\)或\(v_i\)号苹果,具体来说分三种 ...

  8. 雅礼集训 Day2 T3 联盟 解题报告

    联盟 题目描述 \(\text{G}\) 国周边的 \(n\) 个小国家构成一个联盟以抵御 \(\text{G}\) 国入侵, 为互相支援,他们建立了\(n−1\) 条双向通路, 使得任意两个国家可以 ...

  9. 雅礼集训 Day7 T1 Equation 解题报告

    Reverse 题目背景 小\(\text{G}\)有一个长度为\(n\)的\(01\)串\(T\),其中只有\(T_S=1\),其余位置都是\(0\).现在小\(\text{G}\)可以进行若干次以 ...

随机推荐

  1. 利用deadline_timer实现定时器Timer

    // 类似QTimer的定时器 class Timer { typedef void(* handler)(); public: Timer() : m_millseconds() , m_timer ...

  2. svn+apache安装配置

    1.安装httpd,mod_dav_svn,subversion yum install -y httpd mod_dav_svn subversion 2.创建仓库 mkdir /var/www/s ...

  3. JZOJ 5914. 盟主的忧虑

    Description     江湖由 N 个门派(2≤N≤100,000,编号从 1 到 N)组成,这些门派之间有 N-1 条小道将他们连接起来,每条道路都以“尺”为单位去计量,武林盟主发现任何两个 ...

  4. python——标准异常总结

    请参考此网站: Python 标准异常总结 https://fishc.com.cn/forum.php?mod=viewthread&tid=45814&extra=page%3D1 ...

  5. PTA 7-10(图) 旅游规划 最短路问题

    7-10(图) 旅游规划 (25 分) 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果 ...

  6. 【转】正则表达式速查表(http://www.jb51.net/shouce/jquery1.82/regexp.html)

    正则表达式速查表 字符 描述 \ 将下一个字符标记为一个特殊字符.或一个原义字符.或一个向后引用.或一个八进制转义符.例如,“n”匹配字符“n”.“\n”匹配一个换行符.串行“\\”匹配“\”而“\( ...

  7. 亲手搭建一个基于Asp.Net WebApi的项目基础框架2

    本篇目的:封装一些抽象类 1::封装日志相关类 2:封装一个Service操作类 3:封装缓存操作类 4:封装其他一些常用Helper 1.1在Framework项目里面建立好相关操作类文件夹,以便于 ...

  8. ElasticSearch学习笔记(三)-- 查询

    1. URISearch详解与演示 2. QueryDSL简介 3. 字段类查询简介及match-query 4. 相关性算分 5. match-phrase-query 6. query-strin ...

  9. MySQL 5.7.18 压缩包版配置记录

    1.解压到一个目录(建议根目录),比如:D:\mysql2.在系统Path中添加 D:\mysql\bin3.这个版本不带my-default.ini,需要自己写,放在D:\mysql\my.ini, ...

  10. 收集的java面试题

    1.谈谈final, finally, finalize的区别. final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...