首页 技术 正文
技术 2022年11月10日
0 收藏 519 点赞 2,220 浏览 4255 个字

LOJ#2087 国王饮水记

解:这个题一脸不可做…

比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。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,491
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,492
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,132
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,293