链接:
https://www.acwing.com/problem/content/282/
题意:
在一个遥远的国家,一名嫌疑犯是否有罪需要由陪审团来决定。
陪审团是由法官从公民中挑选的。
法官先随机挑选N个人(编号1,2…,N)作为陪审团的候选人,然后再从这N个人中按照下列方法选出M人组成陪审团。
首先,参与诉讼的控方和辩方会给所有候选人打分,分值在0到20之间。
第 i 个人的得分分别记为p[i]和d[i]。
为了公平起见,法官选出的M个人必须满足:辩方总分D和控方总分P的差的绝对值|D-P|最小。
如果选择方法不唯一,那么再从中选择辨控双方总分之和D+P最大的方案。
求最终的陪审团获得的辩方总分D、控方总分P,以及陪审团人选的编号。
思路:
看不太懂题解..考虑二维背包, 选的人数第一维, 辩控差为第二维.
代码:
#include <bits/stdc++.h>
using namespace std;
int Dp[30][1000];
vector<int> Path[210][1000];
int p[210], d[210], sub[210], add[210];
int id[210];
int n, m;
int main()
{
int cnt = 0;
while (~scanf("%d%d", &n, &m))
{
if (n == 0 || m == 0)
break;
memset(Dp, -1, sizeof(Dp));
for (int i = 0;i < m;i++)
{
for (int j = 0;j < 1010;j++)
Path[i][j].clear();
}
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &p[i], &d[i]);
sub[i] = p[i] - d[i];
add[i] = p[i] + d[i];
}
int fix = m * 20;
Dp[0][fix] = 0;
for (int i = 1;i <= n;i++)
{
for (int j = m-1;j >= 0;--j)
{
for (int k = 0;k < 2*fix;k++)
{
if (Dp[j][k] >= 0 && Dp[j+1][k+sub[i]] <= Dp[j][k]+add[i])
{
Dp[j+1][k+sub[i]] = Dp[j][k]+add[i];
Path[j+1][k+sub[i]] = Path[j][k];
Path[j+1][k+sub[i]].push_back(i);
}
}
}
}
int k;
for (k = 0; k <= fix; k++)
{
if (Dp[m][fix - k] >= 0 || Dp[m][fix + k] >= 0)
break;
}
int div;
if (Dp[m][fix - k] > Dp[m][fix + k])
div = fix - k;
else
div = fix + k;
printf("Jury #%d\n", ++cnt);
printf("Best jury has value %d for prosecution and value %d for defence:\n", (div + Dp[m][div] - fix) / 2,
(Dp[m][div] - div + fix) / 2);
for (int i = 0;i < m;i++)
printf(" %d", Path[m][div][i]);
puts("");puts("");
}
return 0;
}