POJ 1015 Jury Compromise (动态规划)

dp[i][j]代表选了i个人,D(J)-P(J)的值为j的状态下,D(J)+P(J)的最大和。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;

const int MAXN = 810;

int n, m;
int dp[24][MAXN];
int path[24][MAXN];
int P[210], D[210];
int sub[210], sum[210];
int maxval, fix;
int ans[210];

bool IfHave( int i, int j, int k )
{
    while ( i > 0 )
    {
        if ( path[i][j] == k ) return true;
        j -= sub[ path[i][j] ];
        --i;
    }
    return false;
}

void DP()
{
    memset( dp, -1, sizeof(dp) );
    dp[0][0+fix] = 0;
    for ( int i = 1; i <= m; ++i )
        for ( int j = -fix; j <= fix; ++j )
        {
            if ( dp[i - 1][j + fix] >= 0 )
            {
                for ( int k = 1; k <= n; ++k )
                {
                    int newdp = dp[i - 1][ j+fix ]+sum[k];
                    int &curdp = dp[i][ j+fix+sub[k] ];
                    if ( !IfHave( i-1, j+fix, k) && newdp > curdp )
                    {
                        path[i][j+fix+sub[k]] = k;
                        curdp = newdp;
                    }
                }
            }
        }

    return;
}

void getPath( int i, int j )
{
    int cnt = 0;
    while ( i > 0 )
    {
        ans[cnt++] = path[i][j];
        j -= sub[ path[i][j] ];
        --i;
    }
    return;
}

int main()
{
    int cas = 0;
    while ( scanf( "%d%d", &n, &m ) == 2 && (n || m) )
    {
        for ( int i = 1; i <= n; ++i )
        {
            scanf( "%d%d", &P[i], &D[i] );
            sub[i] = P[i] - D[i];
            sum[i] = P[i] + D[i];
        }

        fix = 20 * m;
        maxval = 2 * fix;

        DP();

        int anssub, anssum;
        for ( int i = 0; i <= fix; ++i )
        if ( dp[m][fix-i] >= 0 || dp[m][fix+i] >= 0 )
        {
            if ( dp[m][fix-i] > dp[m][fix+i] )
            {
                anssub = fix-i;
                anssum = dp[m][fix-i];
            }
            else
            {
                anssub = fix+i;
                anssum = dp[m][fix+i];
            }
            break;
        }

        getPath( m, anssub );
        int sum1 = 0, sum2 = 0;
        for ( int i = 0; i < m; ++i )
        {
            sum1 += P[ ans[i] ];
            sum2 += D[ ans[i] ];
        }
        printf( "Jury #%d
", ++cas );
        printf( "Best jury has value %d for prosecution and value %d for defence:
", sum1, sum2 );
        sort( ans, ans + m );
        for ( int i = 0; i < m; ++i )
            printf( " %d", ans[i] );
        puts("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GBRgbr/p/3451095.html