简单说一下,动态规划,d[i][j]代表已选择i个人,
P-D差值为j-400时,能取到的P+D最大和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
const int N=800+10;
const int M=20+5;
const int fix=400;
int d[M][N],f[M][N];
int a[N],b[N];
bool find(int u,int d,int t) //查找有没有用过k
{
if(d==0) return true;
if(f[d][u]==t) return false;
while(d>0)
{
u-=a[f[d][u]];
d--;
if(d<=0) break;
if(f[d][u]==t) return false;
}
return true;
}
int main()
{
int n,m,kase=0,a0,b0;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
{
scanf("%d%d",&a0,&b0);
a[i]=a0-b0; //差值
b[i]=a0+b0; //和值
}
memset(d,-1,sizeof(d));
d[0][400]=0; //起始状态
for(int i=0;i<m;i++)
{
for(int j=0;j<N;j++)
if(d[i][j]!=-1)
{
for(int k=0;k<n;k++)
if(find(j,i,k)) //没有被用过
{
if(d[i+1][j+a[k]]<d[i][j]+b[k])
{
d[i+1][j+a[k]]=d[i][j]+b[k]; //更新
f[i+1][j+a[k]]=k; //记录使用的
}
}
}
}
int s,ma,mb=0;
for(int i=0;i<=fix;i++)
{
if(d[m][fix+i]!=-1)
{
ma=fix+i;
mb=d[m][fix+i];
}
if(d[m][fix-i]!=-1&&d[m][fix-i]>mb)
{
ma=fix-i;
mb=d[m][fix-i];
}
if(mb) break;
}
s=ma;
ma-=fix;
int sp[M],cnt=0;
int t=m;
sp[cnt++]=f[t][s]+1;
while(t>0)
{
s-=a[f[t][s]];
t--;
if(t<=0) break;
sp[cnt++]=f[t][s]+1;
}
int pro,def;
pro=(mb-ma)/2+ma;
def=mb-pro;
printf("Jury #%d\n",++kase);
printf("Best jury has value %d for prosecution and value %d for defence:\n",pro,def);
sort(sp,sp+cnt);
for(int i=0;i<cnt;i++)
printf(" %d",sp[i]);
printf("\n\n");
}
return 0;
}