题目链接:
https://codeforces.com/problemset/problem/1703/G
题意:
有 个箱子需要按顺序打开,第 个箱子中有 个金币,可以用好钥匙和坏钥匙去开箱子,好钥匙需要花费 个金币,坏钥匙不花费金币,但是会使当前这个箱子开始到第 个箱子中的金币全部减半。开箱的过程中金币可以是负数的,即可以赊账,问最多能留下多少硬币。
思路:
对于第 个箱子,选择哪个钥匙取决于哪个钥匙的花费少,当坏钥匙的花费小于好钥匙的花费的时候,后面所有的箱子都会采用坏钥匙去开。
因为当前用了坏钥匙,后面的箱子的金币减半,那么坏钥匙的花费就更小了,所以整个开箱的过程分为两段,前面是好钥匙,后面是坏钥匙。
对于坏钥匙而言,最多用 32 次,后面所有的箱子就没有金币了。所以可以采用暴力的做法,枚举使用坏钥匙的第一个箱子,去求出最大的剩余金币。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
LL n, k;
cin >> n >> k;
vector <LL> a(n + 1), s(n + 1), mi(40);
for (int i = 1; i <= n; i ++ ){
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
mi[1] = 2;
for (int i = 2; i <= 32; i ++ )
mi[i] = mi[i - 1] * 2;
LL ans = 0;
for (int i = 0; i <= n; i ++ ){
LL sum = s[i] - i * k;
for (int j = i + 1; j <= min(i + 32LL, n); j ++ ){
sum += a[j] / mi[j - i];
}
ans = max(ans, sum);
}
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
LL T;
cin >> T;
while(T -- ){
solve();
}
return 0;
}
坏钥匙最多 32 个,所以也可以采用 ,定义 为前 个箱子用了 个坏钥匙所获得的最大的收益。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL INF = 1e18;
void solve(){
LL n, k;
cin >> n >> k;
vector <LL> a(n + 1);
vector < vector<LL> > dp(n + 1, vector<LL> (40, -INF) );
for (int i = 1; i <= n; i ++ )
cin >> a[i];
dp[0][0] = 0;
for (int i = 1; i <= n; i ++ ){
for (int j = 0; j <= 33; j ++ ){
dp[i][j] = max(dp[i][j], dp[i - 1][j] + (a[i] >> j) - k); //使用好钥匙
if (j)
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + (a[i] >> j) ); //使用坏钥匙
}
dp[i][33] = max(dp[i][33], dp[i - 1][33]); //注意更新使用了所有坏钥匙的情况
}
LL ans = -INF;
for (int j = 0; j <= 33; j ++ )
ans = max(ans, dp[n][j]);
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
LL T;
cin >> T;
while(T -- ){
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现