POJ 1015 Jury Compromise (dp)
2017-07-17 22:11
447 查看
题意:
有n件物品,每件物品有a价值,b价值,从其中选m件物品,使其总a价值-总b价值的绝对值最小,相等的情况下,总a价值+总b价值最大。
解题思路:
背包既视感,网上很多题解的做法是有问题的,而且那种知道会重复,然后再判断下去掉重复的做法确实很变扭,最后的避免重复的做法就是像01背包一样逆向转移。
设dp[i][j]表示选取i件物品,价值差为j时,价值和的最大值,如果为-1表示不能达到这个价值差。
转移其实也简单。dp[i+1][j+a-b]=max(dp[i+1][j+a-b], dp[i][j]+a+b);
因为j+a-b可能是负数所以可以把零点往右平移一倍的极值。
这是先记录差不考虑绝对值的做法,我按绝对值转移不知道为什么错了,就是会求出来的和会偏小。
为了避免重复,我们再枚举i的时候,应该从m-1往0枚举,这样就防止了每件物品被多次利用。
代码:
#include <iostream>
#include <stdio.h>
#include <vector>
#define ps push_back
using namespace std;
int dp[30][900];
int ans[22];
vector<int>pre[22][804];
int main()
{
int i, j, n, m, k, e=1;
while(~scanf("%d%d", &n, &m))
{
if(n==0 && m==0)break;
for(i=0; i<=m; i++)
{
for(j=0; j<=801; j++)
{
dp[i][j]=-1;
pre[i][j].clear();
}
}
int x, y, xx, yy, z;
dp[0][400]=0;
for(i=1; i<=n; i++)
{
scanf("%d%d", &x, &y);
for(j=m-1; j>=0; j--)
{
for(k=0; k<=800; k++)
{
if(dp[j][k]==-1)continue;
if(dp[j+1][k+x-y]<dp[j][k]+x+y)
{
dp[j+1][k+x-y]=dp[j][k]+x+y;
pre[j+1][k+x-y]=pre[j][k];
pre[j+1][k+x-y].ps(i);
}
}
}
}
for(i=0; dp[m][400+i]==-1 && dp[m][400-i]==-1; i++);
int temp=dp[m][400+i]>dp[m][400-i]?i:-i;
int sumd=(dp[m][400+temp]+temp)/2;
int sump=(dp[m][400+temp]-temp)/2;
printf("Jury #%d\n", e++);
printf("Best jury has value %d for prosecution and value %d for defence:\n", sumd, sump);
for(i=0; i<pre[m][400+temp].size(); i++)
{
printf(" %d", pre[m][400+temp][i]);
}
printf("\n");
}
return 0;
}
有n件物品,每件物品有a价值,b价值,从其中选m件物品,使其总a价值-总b价值的绝对值最小,相等的情况下,总a价值+总b价值最大。
解题思路:
背包既视感,网上很多题解的做法是有问题的,而且那种知道会重复,然后再判断下去掉重复的做法确实很变扭,最后的避免重复的做法就是像01背包一样逆向转移。
设dp[i][j]表示选取i件物品,价值差为j时,价值和的最大值,如果为-1表示不能达到这个价值差。
转移其实也简单。dp[i+1][j+a-b]=max(dp[i+1][j+a-b], dp[i][j]+a+b);
因为j+a-b可能是负数所以可以把零点往右平移一倍的极值。
这是先记录差不考虑绝对值的做法,我按绝对值转移不知道为什么错了,就是会求出来的和会偏小。
为了避免重复,我们再枚举i的时候,应该从m-1往0枚举,这样就防止了每件物品被多次利用。
代码:
#include <iostream>
#include <stdio.h>
#include <vector>
#define ps push_back
using namespace std;
int dp[30][900];
int ans[22];
vector<int>pre[22][804];
int main()
{
int i, j, n, m, k, e=1;
while(~scanf("%d%d", &n, &m))
{
if(n==0 && m==0)break;
for(i=0; i<=m; i++)
{
for(j=0; j<=801; j++)
{
dp[i][j]=-1;
pre[i][j].clear();
}
}
int x, y, xx, yy, z;
dp[0][400]=0;
for(i=1; i<=n; i++)
{
scanf("%d%d", &x, &y);
for(j=m-1; j>=0; j--)
{
for(k=0; k<=800; k++)
{
if(dp[j][k]==-1)continue;
if(dp[j+1][k+x-y]<dp[j][k]+x+y)
{
dp[j+1][k+x-y]=dp[j][k]+x+y;
pre[j+1][k+x-y]=pre[j][k];
pre[j+1][k+x-y].ps(i);
}
}
}
}
for(i=0; dp[m][400+i]==-1 && dp[m][400-i]==-1; i++);
int temp=dp[m][400+i]>dp[m][400-i]?i:-i;
int sumd=(dp[m][400+temp]+temp)/2;
int sump=(dp[m][400+temp]-temp)/2;
printf("Jury #%d\n", e++);
printf("Best jury has value %d for prosecution and value %d for defence:\n", sumd, sump);
for(i=0; i<pre[m][400+temp].size(); i++)
{
printf(" %d", pre[m][400+temp][i]);
}
printf("\n");
}
return 0;
}
相关文章推荐
- POJ 1015 Jury Compromise(DP)
- POJ 1015 Jury Compromise【DP】
- POJ 1015 Jury Compromise ---- DP
- (POJ 1015) Jury Compromise 经典dp问题 (n选m)
- POJ1015-Jury Compromise 以及 uva 323正确二维DP解法
- [dp] poj 1015 Jury Compromise
- POJ 1015 Jury Compromise(双塔DP)
- POJ1015-Jury Compromise-dp
- POJ 1015 Jury Compromise(双塔DP)
- 【dp】POJ 1015 Jury Compromise
- poj 1015 Jury Compromise_dp
- poj 1015 Jury Compromise_dp
- poj - 1015 - Jury Compromise(dp)
- poj 1015 Jury Compromise 状态压缩DP(不压缩也行)
- DP-POJ-1015-Jury Compromise
- poj 1015 Jury Compromise(DP)
- POJ 1015 Jury Compromise(DP)
- POJ1015 Jury Compromise(DP)
- POJ 1015 Jury Compromise(dp坑)
- POJ 1015 Jury Compromise【DP】