P11475 [COCI 2024/2025 #3] 红蓝牌 / Karte
题目背景
译自 COCI 2024/2025 #3 T2。 1s,0.5G \texttt{1s,0.5G} 1s,0.5G。满分为 70 70 70。
题目描述
在 Vito 的桌子上,有 N N N 张编号分别为 1 ∼ N 1\sim N 1∼N 的红牌和 M M M 张编号分别为 1 ∼ M 1\sim M 1∼M 的蓝牌。
将一张红牌和一张蓝牌称为「一对」,给定若干个二元组 ( c , p ) (c,p) (c,p)。若一对牌中,红牌编号为 c c c,蓝牌编号为 p p p,则称这对牌是好对。
一个牌堆包含若干张红牌和若干张蓝牌。定义一个牌堆的价值 w w w 为牌堆中选出一对,使得这个对是一个好对的方案数。
令 r r r 为牌堆中红牌的数量, b b b 为牌堆中蓝牌的数量,定义牌堆的强度 s t r e n g t h \mathrm{strength} strength 为:
s t r e n g t h = w − X ⋅ r − Y ⋅ b \mathrm{strength}=w-X\cdot r-Y\cdot b strength=w−X⋅r−Y⋅b
其中 X X X 和 Y Y Y 是给定的常数。
帮助 Vito 确定:选择若干张红牌和蓝牌构成一个牌堆,这个牌堆的最大强度为多少。注意,他也可以一张牌都不选(即构成一个空的牌堆)。
输入格式
第一行,四个非负整数 N , M , X , Y N,M,X,Y N,M,X,Y。
接下来 N N N 行,每行一个长度为 M M M 的 01 \texttt{01} 01 串,其中第 i i i 行的字符串中第 j j j 位为 1 1 1 表示 ( i , j ) (i,j) (i,j) 是好的,否则表示不是好的。
输出格式
输出一行一个非负整数,表示可以构成的牌堆的最大强度。
输入输出样例 #1
输入 #1
2 2 0 0
11
10
输出 #1
3
输入输出样例 #2
输入 #2
3 3 1 0
111
111
000
输出 #2
4
输入输出样例 #3
输入 #3
3 3 1 1
111
101
011
输出 #3
1
说明/提示
样例解释
样例 1 1 1 中,Vito 可以选择所有的卡牌,能产生 3 3 3 个好对,牌堆的最大强度为 3 3 3。
样例 2 2 2 中,Vito 可以选择编号为 1 , 2 1,2 1,2 的红牌和所有的蓝牌,能产生 6 6 6 个好对,牌堆的最大强度为 4 4 4(由于选择了两张红牌,所以要将好对数减去 2 X = 2 2X=2 2X=2 作为牌堆的强度)。
数据范围
对于 100 % 100\% 100% 的数据,保证:
- 1 ≤ N , M ≤ 21 1\le N,M\le 21 1≤N,M≤21;
- 0 ≤ X , Y ≤ 30 0\le X,Y\le 30 0≤X,Y≤30;
- 输入的字符串中仅包含 0 0 0 和 1 1 1。
| 子任务编号 | 特殊性质 | 得分 |
|---|---|---|
| 1 1 1 | Y = 0 Y=0 Y=0 | 18 18 18 |
| 2 2 2 | 1 ≤ N , M ≤ 9 1\le N,M\le 9 1≤N,M≤9 | 11 11 11 |
| 3 3 3 | 1 ≤ N , M ≤ 15 1\le N,M\le 15 1≤N,M≤15 | 24 24 24 |
| 4 4 4 | 无 | 17 17 17 |
C++实现
# include <bits/stdc++.h>
# define int LL
# define bpc __builtin_popcount
# define geti(x, i) (((x) >> (i)) & 1)
# define each1(i, x) for(auto (i) : (x))
# define each2(i, x) for(auto (&i) : (x))
# define rep(i, a, b) for(int i = (a); i <= (b); ++ i)
# define pre(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
using LL = long long;
const int N = 25;
int n, m, x, y, ans, val, cnt;
char ok[N][N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m >> x >> y;
rep(i, 1, n){
cin >> ok[i] + 1;
}
rep(s, 0, (1 << n) - 1){
val = bpc(s) * (-x);
rep(i, 1, m){
cnt = 0;
rep(j, 0, n - 1){
if(geti(s, j)) cnt += (ok[j + 1][i] - '0');
}
if(cnt - y > 0) val += cnt - y;
}
ans = max(ans, val);
}
cout << ans;
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
用C++实现信奥 P11475 COCI 20242025 #3 红蓝牌 Karte&spm=1001.2101.3001.5002&articleId=151853346&d=1&t=3&u=a91a76f3130c4d88950ef5f46de05f4d)
566

被折叠的 条评论
为什么被折叠?



