/*
基础dp
K - Jury Compromise
题意: n组D[j],P[j]数字,选择m组使选择的D[j]和与P[j]和差最小,如果和差相等,选择D[j]和与P[j]和的总和最大的。
题解:感觉自己菜到怀疑人生。。。
dp[i][j] 代表选第i个,选择的D[]和与P[]和差为j的 最大总和。
path[i][j] 记录前i个选择的组。
ca[i] = D[i]-P[i];
he[i] = D[i]+P[i];
如果选择的前i组和差无法达到j,那么dp[i][j] = -1;
if(k 前面有路径 && k 在前面的路径上没有出现)
dp[i][j+ca[k]] = max(dp[i][j+ca[k]],dp[i-1][j]+he[k]);
j 的原有范围应该是-20*m~20*m , 将其范围加上20*m 变成 0~40*m;
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;
int dp[21][N],path[21][N],res[N];
int a[210],b[210],ca[210],he[210];
int n;
int main()
{
int n,m,cas = 1;
while(cin >> n >> m)
{
if(!n && !m)
break;
for(int i = 0; i < n; i++)
{
cin >> a[i] >> b[i];
ca[i] = a[i]-b[i];
he[i] = a[i]+b[i];
}
memset(dp,-1,sizeof(dp));
memset(path,-1,sizeof(path));
dp[0][20*m] = 0;
for(int i = 0; i < m; i++)
{
for(int j = 0; j <= 40*m; j++)
{
if(dp[i][j] >= 0)
{
for(int k = 0; k < n; k++)
{
int flag = 0;
int pre = path[i][j];
int ans = j;
if(pre == k)
continue;
for(int f = i-1; f >= 1; f--)
{
ans -= ca[pre];
pre = path[f][ans];
if(pre == k)
{
flag = 1;
break;
}
}
if(!flag)
{
if(dp[i+1][j+ca[k]] < dp[i][j]+he[k])
{
dp[i+1][j+ca[k]] = dp[i][j]+he[k];
path[i+1][j+ca[k]] = k;
}
}
}
}
}
// for(int j = 0; j <= 40*m; j++)
// printf("%d %d %d\n",j,path[i+1][j],dp[i+1][j]);
// printf("\n");
}
int mx = 0,id = 0;
for(int i = 0; i <= 20*m; i++)
{
if(dp[m][20*m+i] > mx)
{
mx = dp[m][20*m+i];
id = i;
}
if(dp[m][20*m-i] > mx)
{
mx = dp[m][20*m-i];
id = -i;
}
if(dp[m][20*m+i] != -1 || dp[m][20*m-i] != -1)
break;
}
int ans = id+20*m;
int pre = path[m][ans];
//printf("%d\n",pre);
int ans1 = 0,ans2 = 0;
int k = m;
res[--k] = pre;
ans1 += a[pre];
ans2 += b[pre];
for(int i = m-1; i > 0; i--)
{
ans -= ca[pre];
pre = path[i][ans];
res[--k] = pre;
ans1 += a[pre];
ans2 += b[pre];
//printf("%d\n",pre);
}
sort(res,res+m);
//printf("%d %d\n",id,mx);
printf("Jury #%d\n",cas++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
printf("%d",res[0]+1);
for(int i = 1; i < m; i++)
printf(" %d",res[i]+1);
puts("");
}
return 0;
}
【dp】POJ 1015 Jury Compromise
最新推荐文章于 2019-10-06 01:54:29 发布