Alternative Accounts 贪心匹配
题意:
有n个账号,k场比赛(1 <= k <= 3),每场比赛有m个人参加,账号名分别为\(x_i\),一个人可以有多个账号,但是一个人只能用一个账号参加比赛,问最少有多少个人。
题解:
(大佬教我的)同一场比赛的账号不能在同一个集合里,问最少用几个集合能把数装满,用cnt1,cnt2,cnt3分别记录只出现在第一,二,三场比赛的账号,用cnt12,cnt13,cnt23记录出现在第一二,一三,二三场比赛的账号,那么cnt1和cnt23可以放到同一个集合里,如果cnt1还没放满,可以放cnt2和cnt3的(具体还是看代码
#include <cstdio>
#include <algorithm>
using std::max;
using std::min;
int n, t, m[5], a[5][100010], ans = 0, cnt[100010], c[5][100010];//ans是答案
int main() {
int cnt1 = 0, cnt2 = 0, cnt3 = 0;
int cnt12 = 0, cnt13 = 0, cnt23 = 0;
scanf("%d %d", &n, &t);
for(int i = 1; i <= t; i++) {
scanf("%d", &m[i]);
for(int j = 1; j <= m[i]; j++) {
scanf("%d", &a[i][j]);
cnt[a[i][j]]++;//记录总出现次数
c[i][a[i][j]]++;//记录在第几场出现
}
}
if(t == 1) ans = m[1];
if(t == 2) {
for(int i = 1; i <= n; i++) {
if(cnt[i] == 1) {
if(c[1][i] == 1) cnt1++;
else cnt2++;
}
else if(cnt[i] == 2) ans++;
}
ans += max(cnt1, cnt2);
}
if(t == 3) {
for(int i = 1; i <= n; i++) {
if(cnt[i] == 1) {
if(c[1][i] == 1) cnt1++;
else if(c[2][i] == 1) cnt2++;
else cnt3++;
}
else if(cnt[i] == 2) {
if(c[1][i] == 1 && c[2][i] == 1) cnt12++;
else if(c[1][i] == 1 && c[3][i] == 1) cnt13++;
else if(c[2][i] == 1 && c[3][i] == 1) cnt23++;
}
else if(cnt[i] == 3) ans++;
}
int sum1 = cnt1 + cnt12 + cnt13 + max(0, cnt3 - max(0, cnt1 - cnt23) - cnt12) + max(0, cnt2 - max(0, cnt1 - cnt23) - cnt13) + max(0, cnt23 - cnt1);
int sum2 = cnt2 + cnt12 + cnt23 + max(0, cnt3 - max(0, cnt2 - cnt13) - cnt12) + max(0, cnt1 - max(0, cnt2 - cnt13) - cnt23) + max(0, cnt13 - cnt2);
int sum3 = cnt3 + cnt13 + cnt23 + max(0, cnt1 - max(0, cnt3 - cnt12) - cnt23) + max(0, cnt2 - max(0, cnt3 - cnt12) - cnt13) + max(0, cnt12 - cnt3);
ans += min(sum1, min(sum2, sum3));
}
printf("%d\n", ans);
return 0;
}
原文地址:https://www.cnblogs.com/fanshhh/p/12246835.html
时间: 2024-10-07 13:05:46