您的位置:首页 > 其它

POJ 1015 Jury Compromise (动态规划)

2013-11-30 15:33 316 查看
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\n", ++cas );
printf( "Best jury has value %d for prosecution and value %d for defence:\n", sum1, sum2 );
sort( ans, ans + m );
for ( int i = 0; i < m; ++i )
printf( " %d", ans[i] );
puts("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: