首页 > 代码库 > poj1015

poj1015

题意:n个人,每个人都可以看做有两个参数a,b,从中选m个人,使得ans1=|sigma(a)-sigma(b)|尽可能小,如果存在相等的情况,就保留ans2=sigma(a+b)max。

dp;

dp[j][k]表示选第j个人,使得ans1=k时,最大的ans2;

path[j][k]表示选第j个且ans1=k时的编号//记录路径

v=a-b;s=a+b;

dp[j][k+v[i]]=max(dp[j-1][k]+s[i]);if(dp[j-1][k]>=0 && i not in path[j-1][k])

************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000;

int n,m,P,cas=0;
int a[maxn],b[maxn];
int v[maxn],s[maxn],ans[maxn];
int dp[maxn][maxn],path[maxn][maxn];

void input()
{
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        v[i]=a[i]-b[i];
        s[i]=a[i]+b[i];
    }
}

bool ok(int x,int p,int q)
{
    while(path[p][q]!=x && p)
    {
        q-=v[path[p][q]];
        p--;
    }
    return p ? 0 : 1;
}

void do_dp()
{
    memset(dp,-1,sizeof(dp));
    memset(path,0,sizeof(path));
    dp[0][P=20*m]=0;
    //printf("P=%d\n",P);
    for(int j=1;j<=m;j++)
        for(int k=0;k<=P*2;k++)
            for(int i=1;i<=n;i++)
                if(dp[j-1][k]>=0 && dp[j][k+v[i]]<dp[j-1][k]+s[i] && ok(i,j-1,k))
                {
                    dp[j][k+v[i]]=dp[j-1][k]+s[i];
                    path[j][k+v[i]]=i;
                }
}

void output()
{
    int p=0;
    for(int i=0;i<=P;i++)
        if(dp[m][P+i]>=0 || dp[m][P-i]>=0)
        {
            p = dp[m][P+i] > dp[m][P-i] ? (P+i) : (P-i);
            break;
        }
    //printf("p=%d\n",p);
    memset(ans,0,sizeof(ans));
    int tmp=m;
    while(tmp)
    {
        ans[tmp]=path[tmp][p];
        p-=v[path[tmp][p]];
        tmp--;
    }
    sort(ans+1,ans+1+m);
    int ans1=0,ans2=0;
    for(int i=1;i<=m;i++)ans1+=a[ans[i]],ans2+=b[ans[i]];
    printf("Jury #%d \n",++cas);
    printf("Best jury has value %d for prosecution and value %d for defence: \n",ans1,ans2);
    for(int i=1;i<=m;i++)printf(" %d",ans[i]);
    printf("\n");
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m) && (n || m))
    {
        input();
        do_dp();
        output();
    }
    return 0;
}

************************************************************