当前位置:网站首页>Codeforces Round #806 (Div. 4) D(DP,特判大数)
Codeforces Round #806 (Div. 4) D(DP,特判大数)
2022-07-21 08:53:00 【小酒窝.】
G. Good Key, Bad Key
题意
给定 n n n 个箱子,每个箱子里金钱 a i a_i ai。
每个箱子可以选择用好钥匙开还是用坏钥匙开:
- 用好钥匙开,钥匙花费 k k k,拿走箱子里的所有金钱;
- 用坏钥匙开,钥匙花费 0 0 0,但当前箱子及后面所有箱子中的金钱数都会向下折半。
钥匙花费可以赊账,每个钥匙只能用开一个箱子。
问,这些箱子中的金钱最多能得到多少?
1 ≤ n ≤ 1 0 5 , 0 ≤ k ≤ 1 0 9 , 0 ≤ a i ≤ 1 0 9 1 \leq n \leq 10^5,\ 0 \leq k \leq 10^9,\ 0 \leq a_i \leq 10^9 1≤n≤105, 0≤k≤109, 0≤ai≤109
思路
用 DP 的思路:
定义状态f[i, j]
表示,前 i
个箱子,用 j
个坏钥匙,能拿到的最大金钱数。
状态转移:
- 如果当前位置用坏钥匙的话,那么前
i-1
个位置就用了j-1
个坏钥匙,那么当前箱子的价值为a[i]/2
,除j
次。f[i, j] = f[i-1, j-1] + (a[i]>>j);
- 否则当前位置用好钥匙,那么前
i-1
个位置就用了j
个坏钥匙,好钥匙花费k
,那么当前箱子的价值为a[i]/2
,除j
次,再减去k
。f[i, j] = f[i-1, j] + (a[i]>>j) - k;
但是注意到,n 为 1e5,两重循环就超时了。
但是,ai 最大为 1e9,当选择了 31 个坏钥匙时,最后一个箱子的金钱数就已经是 0 了,如果再多用坏钥匙时,对答案没有贡献,所以只需要循环到 31。
对于后面的钥匙,f[i, 31]
表示前 i 个箱子,用坏钥匙数大于等于 31 时,能拿到的最大金钱数。
#include<bits/stdc++.h>
using namespace std;
#define Ios ios::sync_with_stdio(false),cin.tie(0)
const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N], k;
ll f[N][32];
signed main(){
Ios;
cin >> T;
while(T--)
{
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++)//定义的状态为恰好,需要初始化为负无穷
for(int j=0;j<=31;j++)
f[i][j] = -1e9;
f[0][0] = 0;
ll ans = 0;
for(int i=1;i<=n;i++){
for(int j=0;j<=i && j<=31;j++)
{
f[i][j] = f[i-1][j] + a[i]/(1<<j) - k;
if(j) f[i][j] = max(f[i][j], f[i-1][j-1] + a[i]/(1<<j));
if(j == 31) f[i][j] = max(f[i][j], f[i-1][j]);
if(i==n) ans = max(ans, f[i][j]);
}
}
cout << ans << endl;
}
return 0;
}
/* 1 40 20 12 23 32 43 45 23 65 786 43 23 6 34 23 56 76 43 34 56 7 453 43 65 45 3 423 45 54 45 3223 23 23 23 23 3243 43 65 65 786 78 65 */
但是最后 if(j == 31) f[i][j] = max(f[i][j], f[i-1][j])
不太理解,过段时间再看看。
最后一个状态,f[i, 31]
应该表示的是,前 i 个箱子,用了大于等于31个坏钥匙得到的最大钱数。
对于 j=31 时,不加特判的时候,如果第 i 个箱子用好钥匙,其应该从 f[i-1, 31] 转移过来,更新为 f[i-1, 31] - k
;如果用坏钥匙,更新为 f[i-1, 30]
。
正如上面说的,f[i, 31]
表示的是用了大于等于31个坏钥匙的情况,假设用了前 i 个位置40个坏钥匙,f[i, 40] 应该是从 f[i-1, 39] 来转移,但在这个状态定义中,就是从 f[i-1, 31]
来转移,所以对于 j=31(实际上表示的是用了大于等于31个坏钥匙, j>=31)时,答案可能是 f[i-1, 31]
。但是代码中并不能从这个状态来转移,所以要在 j==31 时额外加上。
当 j==31 时,此时第 i 个箱子的权值已经是 0 了,没必要花费 k 用好钥匙了,用坏钥匙即可,所以这时好钥匙更新可以去掉。
所以比较准确的写法应该是这样:
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++) //定义的状态为恰好,需要初始化为负无穷
for(int j=0;j<=31;j++)
f[i][j] = -1e9;
f[0][0] = 0;
ll ans = 0;
for(int i=1;i<=n;i++){
for(int j=0;j<=i && j<=31;j++)
{
if(j != 31) f[i][j] = f[i-1][j] + (a[i]>>j) - k;
if(j) f[i][j] = max(f[i][j], f[i-1][j-1] + (a[i]>>j));
if(j == 31) f[i][j] = max(f[i][j], f[i-1][j]);
if(i==n) ans = max(ans, f[i][j]);
}
}
cout << ans << endl;
最后的状态没有枚举,但确实存在,所以其转移的时候也不能忽略。
这题还可以用贪心,好钥匙都用在前面,坏钥匙都用到后面,枚举用了多少好钥匙即可。
但是如果对于每个箱子好钥匙的花费不一样,是不是就只能用 dp 了呢?
边栏推荐
- m在ISE平台下使用verilog开发基于FPGA的GMSK调制器
- JVM memory layout detailed, illustrated, well written!
- 父子进程、僵尸进程和孤儿进程
- 大佬们我在diea本地运行没问题,放在服务器上运行,cdc连接不上咋回事,数据库ip可以ping通
- Rust learning notes -rust language foundation
- 数字游戏:n人报数,报3的倍数的人离开,其余继续
- Celebration code
- 动态规矩-数组压缩优化
- windows10上安装mysql 5.7.37
- 06-1. Friends, initialization list initialization, Nei 'Bu
猜你喜欢
JVM memory layout detailed, illustrated, well written!
05-1. Default member function: copy constructor, assignment operator overload
ssh方式登录huawei设备
COVID-19-20——基于VNet3D分割网络的基础方法
一文让你掌握22个神经网络训练技巧
3. Project structure of source code analysis of Nacos configuration center
LeetCode 146:LRU 缓存
风控系统,Flink+Clickhouse实现!
Neural network plus attention mechanism, accuracy does not rise but fall?
m在simulink进行DS-CDMA建模,然后通过MATLAB调用simulink模型进行误码率仿真
随机推荐
Payment system - reconciliation system
Window functions in sparksql
js中批量修改对象中的属性值
BGP—— 边界网关协议
Riding the wind and waves, the road of digital transformation in the era of financial technology
如何用Go实现一个异步网络库?
如何在 Kubernetes 集群中集成 Kata
2022.7.20-----leetcode.1260
The Linux server installed the graphical interface, but failed to display the initialization graphical interface when installing the database
基于php开发的学生成绩管理系统
Database generates HTML document
多重背包问题代码模板
CRM concept: understand the concepts of leads, prospect, MQL and SQL
一文让你掌握22个神经网络训练技巧
【着色器实现Television信号三原色闪烁效果_Shader效果第五篇】
IDE(集成开发环境)是什么
点击按钮,丝滑的返回顶部
Group knapsack problem
利用正则回溯最大次数上限进行绕过
Dynamic programming multiple knapsack one dimension