解:这个题一脸不可做...

比1小的怎么办啊,好像没用,扔了吧。

先看部分分,n = 2简单,我会分类讨论!n = 4简单,我会搜索!n = 10,我会剪枝!

k = 1怎么办,好像选的那些越大越好啊,那么我就排序之后枚举后缀!

k = INF怎么办啊,好像最优策略是从小到大一个一个连通啊,那直接模拟好了。

写一写,有40分了。

别的怎么办啊,拿搜索找规律吧?于是发现一个规律(伪):最优策略一定是单独选择最后k - 1个,和前面的一个后缀。

于是枚举后缀,然后模拟后面的部分,成功得到了61分!

 #include <bits/stdc++.h>

 // ---------- decimal lib start ----------

 // ---------- decimal lib end ----------

 const int N = ;

 int n, k, p;
Decimal a[N]; inline void output(Decimal x) {
std::cout << x.to_string(p + ) << std::endl;
return;
} inline void output(double x) {
printf("%.10f\n", x);
return;
} inline void out(int x) {
for(int i = ; i < n; i++) {
printf("%d", (x >> i) & );
}
return;
} namespace bf { const double eps = 1e-; double ans = , a[N], temp[][];
int lm, pw[], Ans[N], now[N]; void DFS(int x) {
/// check
double large();
for(int i = ; i <= n; i++) {
if(large < a[i]) large = a[i];
}
if(large < ans + eps) {
return;
}
if(fabs(large - a[]) < eps || x > k) {
if(ans < a[]) {
ans = a[];
memcpy(Ans + , now + , x * sizeof(int));
}
return;
} for(int i = ; i <= n; i++) {
temp[x - ][i] = a[i];
}
for(int s = lm - ; s > ; s--) {
if(!(s - (s & (-s)))) continue;
double tot = ;
int cnt = ;
int t = s;
while(t) {
int tt = pw[t & (-t)] + ;
tot += a[tt];
cnt++;
t ^= << (tt - );
}
tot /= cnt;
t = s;
while(t) {
int tt = pw[t & (-t)] + ;
a[tt] = tot;
t ^= << (tt - );
}
now[x] = s;
DFS(x + );
t = s;
while(t) {
int tt = pw[t & (-t)] + ;
a[tt] = temp[x - ][tt];
t ^= << (tt - );
}
}
now[x] = ;
return;
} inline void solve() { /// DFS
lm = << n;
for(int i = ; i < n; i++) {
pw[ << i] = i;
}
for(int i = ; i <= n; i++) {
a[i] = ::a[i].to_double();
}
DFS(); output(ans); /*for(int i = 1; i <= k + 1; i++) {
out(Ans[i]); printf(" ");
}
puts("");*/
return;
}
} int main() { //freopen("in.in", "r", stdin); scanf("%d%d%d", &n, &k, &p);
for(int i = , x; i <= n; i++) {
scanf("%d", &x);
a[i] = x;
} std::sort(a + , a + n + );
if(n == ) {
output(a[]);
return ;
}
if(n == ) {
if(a[] > a[]) {
output(a[]);
}
else {
a[] = (a[] + a[]) / ;
output(a[]);
}
return ;
}
if(a[] >= a[n]) {
output(a[]);
return ;
}
if(k == ) {
Decimal tot = a[], ans = a[];
int cnt = ;
for(int i = n; i >= ; i--) {
cnt++;
tot += a[i];
ans = std::max(ans, tot / cnt);
}
output(ans);
return ;
}
if(k >= n - ) {
for(int i = ; i <= n; i++) {
if(a[] > a[i]) continue;
a[] = (a[] + a[i]) / ;
}
output(a[]);
return ;
}
if(n <= ) {
bf::solve();
return ;
}
else {
Decimal tot = a[], ans = a[];
int cnt = ;
for(int i = n - k + ; i >= ; i--) {
cnt++;
tot += a[i];
ans = std::max(ans, tot / cnt);
}
a[] = ans;
for(int i = n - k + ; i <= n; i++) {
if(a[] > a[i]) continue;
a[] = (a[] + a[i]) / ;
}
output(a[]);
return ;
}
return ;
}

61分代码

正确的规律:最优策略一定是把一个后缀分成连续若干段。

于是以此DP,设f[i][j]表示前i次操作取到了j,此时1号点的最大值。转移就枚举从哪来即可。注意初始化。

 #include <bits/stdc++.h>

 // ---------- decimal lib start ----------

 const int PREC = ;

 // ---------- decimal lib end ----------

 const int N = ;

 int n, k, p;
Decimal a[N]; inline void output(Decimal x) {
std::cout << x.to_string(p + ) << std::endl;
return;
} inline void output(double x) {
printf("%.10f\n", x);
return;
} inline void out(int x) {
for(int i = ; i < n; i++) {
printf("%d", (x >> i) & );
}
return;
} namespace bf { const double eps = 1e-; double ans = , a[N], temp[][];
int lm, pw[], Ans[N], now[N]; void DFS(int x) {
/// check
double large();
for(int i = ; i <= n; i++) {
if(large < a[i]) large = a[i];
}
if(large < ans + eps) {
return;
}
if(fabs(large - a[]) < eps || x > k) {
if(ans < a[]) {
ans = a[];
memcpy(Ans + , now + , x * sizeof(int));
}
return;
} for(int i = ; i <= n; i++) {
temp[x - ][i] = a[i];
}
for(int s = lm - ; s > ; s--) {
if(!(s - (s & (-s)))) continue;
double tot = ;
int cnt = ;
int t = s;
while(t) {
int tt = pw[t & (-t)] + ;
tot += a[tt];
cnt++;
t ^= << (tt - );
}
tot /= cnt;
t = s;
while(t) {
int tt = pw[t & (-t)] + ;
a[tt] = tot;
t ^= << (tt - );
}
now[x] = s;
DFS(x + );
t = s;
while(t) {
int tt = pw[t & (-t)] + ;
a[tt] = temp[x - ][tt];
t ^= << (tt - );
}
}
now[x] = ;
return;
} inline void solve() { /// DFS
lm = << n;
for(int i = ; i < n; i++) {
pw[ << i] = i;
}
for(int i = ; i <= n; i++) {
a[i] = ::a[i].to_double();
}
DFS(); output(ans); /*for(int i = 1; i <= k + 1; i++) {
out(Ans[i]); printf(" ");
}
puts("");*/
return;
}
} Decimal f[][];
int sum[N]; inline void solve() {
int I = ;
while(a[] > a[I]) ++I;
for(int i = ; i <= n; i++) {
f[][i] = a[];
}
for(int i = ; i <= k; i++) {
f[i][I - ] = a[];
for(int j = I; j <= n; j++) {
/// f[i][j]
f[i][j] = f[i - ][j];
for(int p = I - ; p < j; p++) {
Decimal t = (f[i - ][p] + sum[j] - sum[p]) / (j - p + );
if(f[i][j] < t) {
f[i][j] = t;
}
}
//printf("i = %d j = %d f = ", i, j); output(f[i][j]);
}
}
output(f[k][n]);
return;
} int main() { //freopen("in.in", "r", stdin);
//printf("%d \n", (sizeof(f)) / 1048576); scanf("%d%d%d", &n, &k, &p);
for(int i = , x; i <= n; i++) {
scanf("%d", &x);
a[i] = x;
} std::sort(a + , a + n + );
for(int i = ; i <= n; i++) {
sum[i] = sum[i - ] + (int)(a[i].to_double() + 0.5);
}
if(n == ) {
output(a[]);
return ;
}
if(n == ) {
if(a[] > a[]) {
output(a[]);
}
else {
a[] = (a[] + a[]) / ;
output(a[]);
}
return ;
}
if(a[] >= a[n]) {
output(a[]);
return ;
}
if(k == ) {
Decimal tot = a[], ans = a[];
int cnt = ;
for(int i = n; i >= ; i--) {
cnt++;
tot += a[i];
ans = std::max(ans, tot / cnt);
}
output(ans);
return ;
}
if(k >= n - ) {
for(int i = ; i <= n; i++) {
if(a[] > a[i]) continue;
a[] = (a[] + a[i]) / ;
}
output(a[]);
return ;
}
if(n <= ) {
bf::solve();
return ;
}
else {
solve();
return ;
}
return ;
}

60分代码

考虑如何优化这个DP。

LOJ#2087 国王饮水记的更多相关文章

  1. 【BZOJ4654】【NOI2016】国王饮水记(动态规划,斜率优化)

    [BZOJ4654][NOI2016]国王饮水记(动态规划,斜率优化) 题面 BZOJ 洛谷 题解 首先肯定是找性质. 明确一点,比\(h_1\)小的没有任何意义. 所以我们按照\(h\)排序,那么\ ...

  2. [UOJ#223][BZOJ4654][Noi2016]国王饮水记

    [UOJ#223][BZOJ4654][Noi2016]国王饮水记 试题描述 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳 ...

  3. luogu P1721 [NOI2016]国王饮水记 斜率优化dp 贪心 决策单调性

    LINK:国王饮水记 看起来很不可做的样子. 但实际上还是需要先考虑贪心. 当k==1的时候 只有一次操作机会.显然可以把那些比第一个位置小的都给扔掉. 然后可以得知剩下序列中的最大值一定会被选择. ...

  4. [Noi2016]国王饮水记

    来自FallDream的博客,未经允许,请勿转载,谢谢. 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳蚤实在太多,跳蚤国王 ...

  5. BZOJ4654/UOJ223 [Noi2016]国王饮水记

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. uoj233/BZOJ4654/洛谷P1721 [Noi2016]国王饮水记 【dp + 斜率优化】

    题目链接 uoj233 题解 下面不加证明地给出几个性质: 小于\(h[1]\)的城市一定是没用的 任何城市联通包含\(1\)且只和\(1\)联通一次 联通顺序从小到大最优 单个联通比多个一起联通要优 ...

  7. [NOI 2016]国王饮水记

    Description 题库链接 给出 \(n\) 个水杯,每个水杯装有不同高度的水 \(h_i\) ,每次可以指定任意多水杯用连通器连通后断开,问不超过 \(k\) 次操作之后 \(1\) 号水杯的 ...

  8. *UOJ#223. 【NOI2016】国王饮水记

    $n \leq 8000$的数列,问不超过$m \leq 1e9$次操作后第一个数字最大是多少.操作:选一些数,把他们变成他们的平均值.需要保留$p \leq 3000$位小数,提供了一个小数高精度库 ...

  9. BZOJ4654 NOI2016国王饮水记(动态规划+三分)

    有很多比较显然的性质.首先每个城市(除1外)至多被连通一次,否则没有意义.其次将城市按水位从大到小排序后,用以连通的城市集合是一段前缀,并且不应存在比1城市还小的.然后如果确定了选取的城市集合,每次选 ...

随机推荐

  1. vue鼠标悬停事件

    v-bind:title="message" <!DOCTYPE html> <html lang="en"> <head> ...

  2. 第三次上机,ADO接口的使用

    <html> <head> <title>Reg</title> </head> <body><center> &l ...

  3. 用app.net Core搞掂多国语言网站

    Asp.net Core 中文文档很少,你可以看英文的,不过英文的也是说的有点乱.这篇文章是干货. 1. 配置好你的WebApplication,使他可以支持国际化语言,修改文档Startup.cs ...

  4. packagereference 里面的资产是怎么回事?

    <PackageReference Include="Newtonsoft.Json" Version="9.0.1"> <ExcludeAs ...

  5. js实现自定义修改网页中表格信息

    项目中的打印页面,为提高用户体验,需要增自定修改表格内容的功能,以下是使用示意图(双击td标签部分的内容,可自定义修改): 以下是js插件源码,存为edit.js文件: var tbl, tbt; v ...

  6. .Net Core 在Linux服务器下部署程序--(4). 前端ReactWeb应用部署

    确认第二步中的软件已经安装完成 Nodejs前端Web服务器 Zip与UnZip压缩包软禁 nrm前端包源管理器 PM2前端Web程序守护进程 创建部署文件夹 如果已经执行过( 3. 租户平台后端程序 ...

  7. GDB调试指南-变量查看

    前言 在启动调试以及设置断点之后,就到了我们非常关键的一步-查看变量.GDB调试最大的目的之一就是走查代码,查看运行结果是否符合预期.既然如此,我们就不得不了解一些查看各种类型变量的方法,以帮助我们进 ...

  8. 2018-2019-2 20175217 实验二《Java面向对象程序设计》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吴一凡 学号:20175217 指导教师:娄嘉鹏 实验日期:2019年4月15日 实验时间:--- 实验序号:实验二 实验名称:Jav ...

  9. 基于令牌桶算法实现的SpringBoot分布式无锁限流插件

    本文档不会是最新的,最新的请看Github! 1.简介 基于令牌桶算法和漏桶算法实现的纳秒级分布式无锁限流插件,完美嵌入SpringBoot.SpringCloud应用,支持接口限流.方法限流.系统限 ...

  10. FAST LOW-RANK APPROXIMATION FOR COVARIANCE MATRICES

    目录 Nystorm method 低秩逼近 矩阵乘法的逼近 Belabbas M A, Wolfe P J. Fast Low-Rank Approximation for Covariance M ...