题目链接
本题是ICPC亚洲区域赛Daejeon赛区2011年的 D 题。
题意
一种武器装备按5个方面分别打分(0~10000),若同时选择了多种装备,则每个方面的得分为这些装备此方面得分的最大值。给出n(1≤n≤10000)种装备的打分数值,求选择其中k(1≤k≤n)种装备时最大总得分。
分析
如果k≥5,则只需要对每方面得分从n个装备种找到最大值,求和即可。
如果k≤5,其实也可以借鉴前一种的思路:只要把某几个方面的得分“捆绑”在一起,当成一个方面,将5个方面缩减成k个方面,用同样的方式可求。此时需要dfs枚举“捆绑”的所有可能,记录某个“捆绑”情况,可以用数组a[5],a[i]=j表示第i(1≤i≤5)个方面最终“捆绑”到了第j(1≤j≤k,k<5)个方面。
AC代码
#include <iostream>
using namespace std;
#define N 10100
#define M 5
int r[N][M], a[M], ans, n, k;
void dfs(int curr = 0) {
if (curr == M) {
int m[M] = {0}, s = 0;
for (int i=0; i<n; ++i) {
int t[M] = {0};
for (int j=0; j<M; ++j) t[a[j]] += r[i][j];
for (int j=0; j<k; ++j) m[j] = max(m[j], t[j]);
}
for (int i=0; i<k; ++i) s += m[i];
ans = max(ans, s);
} else for (int i=0; i < k; ++i) {
a[curr] = i;
dfs(curr+1);
}
}
int solve() {
cin >> n >> k;
for (int i=0; i<n; ++i) for (int j=0; j<M; ++j) cin >> r[i][j];
ans = 0;
if (k >= M) {
for (int i=0; i<M; ++i) {
int m = 0;
for (int j=0; j<n; ++j) m = max(m, r[j][i]);
ans += m;
}
} else dfs();
return ans;
}
int main() {
int t; cin >> t;
while (t--) cout << solve() << endl;
return 0;
}