题解:UVA323 Jury Compromise
Super_Masarada · · 题解
题目分析
这是一个有很多个维度的 01 背包。把
- “人数”,每个人的人数都是
1 ,最终要填满容量为M 的背包。 - “辩方得分”,辩方打的分数
d_i 。 - “控方得分”,控方打的分数
p_i 。
考虑按照人数划分阶段。当枚举完前
初始时
但是这种方法没有很好的利用 dp 中“价值”这一维度。事实上,可以把控方辩方的分差
设
初始时
值得注意的是,
最后输出方案时,根据
Code
#include <bits/stdc++.h>
namespace SXL {
using std::max;
constexpr int MAXN = 200;
constexpr int MAXM = 20;
constexpr int MAXK = 800;
constexpr int pyl = 400;
int n,m;
int d[MAXN + 5],p[MAXN + 5];
int f[MAXN + 5][MAXM + 5][MAXK + 5];
int tot;
int cnt;
int ans[MAXM + 5];
void work() {
memset(f,128,sizeof(f));
tot = 0;
for(int i = 1;i <= n;i++) {
scanf("%d%d",d + i,p + i);
}
f[0][0][pyl] = 0;
for(int i = 1;i <= n;i++) {
for(int j = 0;j <= m;j++) {
for(int k = 0;k <= MAXK;k++) {
f[i][j][k] = f[i - 1][j][k];
int c = k - d[i] + p[i];
if(c < 0 || c > MAXK || j == 0) continue;
f[i][j][k] = max(f[i][j][k],f[i - 1][j - 1][c] + d[i] + p[i]);
}
}
}
int v = 0;
while(f[n][m][pyl + v] < 0 && f[n][m][pyl - v] < 0) v++;
if(f[n][m][pyl - v] > f[n][m][pyl + v]) v = pyl - v;
else v = pyl + v;
int i = n,j = m;
while(i) {
if(f[i][j][v] == f[i - 1][j][v]) {
i--;
continue;
}
ans[++tot] = i;
v = v - d[i] + p[i];
i--;
j--;
}
int a1 = 0,a2 = 0;
for(int i = 1;i <= tot;i++) {
a1 += d[ans[i]];
a2 += p[ans[i]];
}
printf("Jury #%d\n",++cnt);
printf("Best jury has value %d for prosecution and value %d for defence:\n",a1,a2);
for(int i = tot;i >= 1;i--) {
printf(" %d",ans[i]);
}
puts("");
puts("");
}
void main() {
while(true) {
scanf("%d%d",&n,&m);
if(!n && !m) break;
work();
}
}
}
int main() {
SXL::main();
return 0;
}