codeforces1914 C~F

C - Quests

要解释第 i 个任务,前面的任务必须全部解锁。解锁后,剩余的次数可以重复做前面的任务。

先记录解锁到第 i 个任务的总经验值,记录前 i 个任务的最大值。

解锁到第 i 个,让剩余次数乘前面任务中b最大的。

如果 k > n k>n k>n 再算 m a x ( s u m , s a [ i ] + t ∗ m b [ i ] ) max(sum, sa[i] + t*mb[i]) max(sum,sa[i]+t∗mb[i]) 。

c++ 复制代码
#include<iostream>
#include<map>
#include<vector>
#include<string>
using namespace std;
void solve() {
	int n, k;
	cin >> n >> k;
	vector<int>a(n), b(n);
	vector<int>sa(n, 0), mb(n, 0);
	for (int i = 0; i < n; i++) cin >> a[i];

	for (int i = 0; i < n; i++)	cin >> b[i];

	sa[0] = a[0];
	for (int i = 1; i < n; i++)	sa[i] = sa[i - 1] + a[i];
	//前缀ai和

	mb[0] = b[0];
	for (int i = 1; i < n; i++)	mb[i] = max(b[i], mb[i - 1]);
	//前bi中最大的

	int sum = 0;
	for (int i = 0; i < min(n, k); i++) {
		int t = k - 1 - i;
		sum = max(sum, sa[i] + t*mb[i]);
	}
	if (k > n) {
		sum = max(sum, sa[n - 1] + mb[n - 1] * (k - n));
	}
	cout << sum << endl;


}
int main() {
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
}

D - Three Activities

三个日子 x , y , z x,y,z x,y,z ,要 a [ x ] + b [ y ] + c [ z ] a[x]+b[y]+c[z] a[x]+b[y]+c[z] 最大。并且 x = = y ∣ ∣ x = = z ∣ ∣ y = = z x==y||x==z||y==z x==y∣∣x==z∣∣y==z 这样的日子是不行的。

先找出每个数组前三个最大的,记录元素的值和下标。再枚举所有组合 3 ∗ 3 = 27 3*3=27 3∗3=27 种。找最大值

c++ 复制代码
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include <functional>
using namespace std;
typedef long long ll;
bool cmp(pair<int, int>a, pair<int, int>b) {
	return a.first > b.first;
}
void solve() {
	int n;
	cin >> n;
	vector<pair<int, int>>a, b, c;
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		a.push_back({x, i});
	}
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		b.push_back({x, i});
	}
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		c.push_back({x, i});
	}
	sort(a.begin(),a.end(),cmp);
	sort(b.begin(),b.end(),cmp);
	sort(c.begin(),c.end(),cmp);
	
	ll mx=0;
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 3; j++) {
			for (int k = 0; k < 3; k++) {
				if(a[i].second==b[j].second||a[i].second==c[k].second||b[j].second==c[k].second) continue;
				mx=max((ll)(a[i].first+b[j].first+c[k].first),mx);
			}
		}
	}
	cout<<mx<<endl;
}
int main() {
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
}

E - Game with Marbles (Easy )

两人轮流选,爱丽丝要最大化得分,鲍勃要最小化得分。用dp数组存每个状态的最优贡献。

mask 二进制位为1表示被选,0:未选的。

d p [ m a s k ] dp[mask] dp[mask] 表示选 mask 时,双方的最优策略。最终答案是 d p [ 0 ] dp[0] dp[0]

_ _ b u i l t i n _ p o p c o u n t ( m a s k ) \\ builtin\_popcount(mask) __builtin_popcount(mask) 统计 mask 中二进制1的个数。为偶数时爱丽丝选,奇数鲍勃选。


dp+逆序遍历+位掩码

为什么逆序遍历?

计算 d p [ m a s k ] dp[mask] dp[mask] 时,需要依赖 "选了一个新颜色后的状态" t 的 d p [ t ] dp[t] dp[t] 的值。

当 k = = n k == n k==n 时, m a s k = ( 1 < < n ) − 1 mask = (1<<n)-1 mask=(1<<n)−1(二进制全 1),没有可再选的颜色,游戏结束,贡献为 0。

m a s k & ( 1 < < j ) mask \& (1 << j) mask&(1<<j) 判断整数mask的第 j 个二进制位是否为1,看该颜色是否被选。非0->颜色已选 就跳过

m a s k ∣ ( 1 < < j ) mask | (1 << j) mask∣(1<<j) 选择颜色 j 将整数mask第 j 个二进制位设置为1其他位不变,来更新状态。实现状态转移


c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve() {
	int n;
	cin >> n;
	vector<ll>a(n), b(n);
	for (int i = 0; i < n; i++) cin >> a[i];
	for (int i = 0; i < n; i++) cin >> b[i];
	vector<ll>dp(1 << n, 0);
	for (int mask = (1 << n) - 2; mask >= 0; mask--) {
		int k = __builtin_popcount(mask);
		if (k % 2 == 0) {//爱丽丝
			dp[mask] = -1e18;
			for (int j = 0; j < n; j++) {
				if (mask & (1 << j)) continue;
				int t = mask | (1 << j);
				dp[mask] = max(dp[mask], a[j] - 1 + dp[t]);
			}
		} else {//鲍勃
			dp[mask] = 1e18;
			for (int j = 0; j < n; j++) {
				if (mask & (1 << j)) continue;
				int t = mask | (1 << j);
				dp[mask] = min(dp[mask], 1 - b[j] + dp[t]);
			}
		}
	}
	cout << dp[0] << endl;

}
int main() {
	int T;
	cin >> T;
	while (T--) {
		solve();
	}
}

F - Game with Marbles (Hard )

方法二:贪心

对于选择问题,谁先选哪个元素会影响总得分。

假设只有两种元素, x = ( a 1 , a 2 ) x=(a_1,a_2) x=(a1,a2) y = ( b 1 , b 2 ) y=(b_1,b_2) y=(b1,b2) ,爱丽丝先选有两种情况:

  • 爱丽丝选 x ,鲍勃选 y : ( a 1 − 1 ) + ( 1 − b 2 ) = a 1 − b 2 (a_1-1)+(1-b_2)=a_1-b_2 (a1−1)+(1−b2)=a1−b2
  • 爱丽丝选 y , 鲍勃选 x : ( a 2 − 1 ) + ( 1 − b 1 ) = a 2 − b 1 (a_2-1)+(1-b_1)=a_2-b_1 (a2−1)+(1−b1)=a2−b1

( a 1 − b 2 ) − ( a 2 − b 1 ) = ( a 1 + b 1 ) − ( a 2 + b 2 ) (a_1-b_2)-(a_2-b_1)=(a1 + b1) - (a2 + b2) (a1−b2)−(a2−b1)=(a1+b1)−(a2+b2)

如果a1 + b1 > a2 + b2:第一种顺序(先 x 后 y)总贡献更大,对爱丽丝更有利;

反之,第二种顺序更好。

所以对 a [ i ] + b [ i ] a[i]+b[i] a[i]+b[i] 排序,然后两人轮流选择。

c++ 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool cmp(pair<ll, ll>x, pair<ll, ll>y) {
	return x.first + x.second > y.first + y.second;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		vector<ll> a(n), b(n);
		for (int i = 0; i < n; i++) cin >> a[i];
		for (int i = 0; i < n; i++) cin >> b[i];

		ll sum = 0;
		vector<pair<ll, ll>>c;
		for (int i = 0; i < n; i++) {
			c.push_back({a[i], b[i]});
		}
		sort(c.begin(), c.end(), cmp);
		for (int i = 0; i < n; i++) {
			if (i % 2==0) {
				sum += c[i].first - 1;
			} else sum += 1 - c[i].second;
		}
		cout << sum << '\n';
	}
	return 0;
}
相关推荐
qq_401700412 小时前
嵌入式用Unix时间的优势及其C语言转换
服务器·c语言·unix
mit6.8244 小时前
bfs|栈
算法
CoderYanger5 小时前
优选算法-栈:67.基本计算器Ⅱ
java·开发语言·算法·leetcode·职场和发展·1024程序员节
jllllyuz6 小时前
Matlab实现基于Matrix Pencil算法实现声源信号角度和时间估计
开发语言·算法·matlab
稚辉君.MCA_P8_Java6 小时前
DeepSeek 插入排序
linux·后端·算法·架构·排序算法
多多*6 小时前
Java复习 操作系统原理 计算机网络相关 2025年11月23日
java·开发语言·网络·算法·spring·microsoft·maven
.YM.Z7 小时前
【数据结构】:排序(一)
数据结构·算法·排序算法
Chat_zhanggong3457 小时前
K4A8G165WC-BITD产品推荐
人工智能·嵌入式硬件·算法
百***48077 小时前
【Golang】slice切片
开发语言·算法·golang
墨染点香7 小时前
LeetCode 刷题【172. 阶乘后的零】
算法·leetcode·职场和发展