poj1015——Jury Compromise
2014-08-23 15:55
239 查看
题意:n(1~200)个候选人,辩方和控方分别对他们打分(0~20)分别为p、d,从其中选出m个人,要求——这m个人辩方总分和控方总和的差值最小,如果存在多种情况则选辩方、控方总和最大的。
输入:n,m,p[i],d[i]
输出:sum(p[i]),sum(d[i]),选择的m个人(按编号的升序)
分析:动态规划
1、用到2个数组——dp[i][j]:表示取i个候选人,使其辩控差为j的所有方案中,辩控和最大的方案的辩控和
path[i][j]:记录所选定的候选人的编号
2、由于辩控差可以为负数,而我们要保证dp[i][j]中j的非负性,所以设置一个修正值real_m=m*20,这样辩控差 区间从[-400,400]变成[0,800]
3、主体就是三重循环——i从1到m,j从0到2*real_m,k从1到n,找到满足条件的k就可以记录到path数组中去,
详情见代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct P
{
int sum,sub;
};
P caipan[201];
int path[21][801],dp[21][801];
bool OK(int a,int b,int c)
{
while(a>0&&path[a][b]!=c)
{
b-=caipan[path[a][b]].sub;
a--;
}
if(a==0)return true;
else return false;
}
int main()
{
int n,m,i,j,k,cas=1,id[21];
while(scanf("%d%d",&n,&m),n+m)
{
memset(caipan,0,sizeof(caipan));
for(i=1;i<=n;i++)
{
int p,d;
scanf("%d%d",&p,&d);
caipan[i].sum=p+d;
caipan[i].sub=p-d;
}
memset(dp,-1,sizeof(dp));
memset(path,0,sizeof(path));
int real_m=m*20;
dp[0][real_m]=0;
for(i=1;i<=m;i++)
for(j=0;j<=2*real_m;j++)
if(dp[i-1][j]>=0)
{
for(k=1;k<=n;k++)
if(dp[i][j+caipan[k].sub]<dp[i-1][j]+caipan[k].sum&&OK(i-1,j,k))
{
dp[i][j+caipan[k].sub]=dp[i-1][j]+caipan[k].sum;
path[i][j+caipan[k].sub]=k;
}
}
for(k=0;k<=real_m;k++)
if(dp[m][real_m-k]>=0||dp[m][real_m+k]>=0)break;
int tmp=dp[m][real_m-k]>dp[m][real_m+k]?(real_m-k):(real_m+k);
//printf("+++%d\n",tmp);
int sum_p=(dp[m][tmp]+(tmp-real_m))/2;
int sum_d=(dp[m][tmp]-(tmp-real_m))/2;
for(i=m,j=0;i>0;i--)
{
id[j]=path[i][tmp];
tmp-=caipan[path[i][tmp]].sub;
j++;
}
sort(id,id+m);
printf("Jury #%d\n",cas++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",sum_p,sum_d);
for(i=0;i<m;i++)
printf(" %d",id[i]);
printf("\n\n");
}
return 0;
}
输入:n,m,p[i],d[i]
输出:sum(p[i]),sum(d[i]),选择的m个人(按编号的升序)
分析:动态规划
1、用到2个数组——dp[i][j]:表示取i个候选人,使其辩控差为j的所有方案中,辩控和最大的方案的辩控和
path[i][j]:记录所选定的候选人的编号
2、由于辩控差可以为负数,而我们要保证dp[i][j]中j的非负性,所以设置一个修正值real_m=m*20,这样辩控差 区间从[-400,400]变成[0,800]
3、主体就是三重循环——i从1到m,j从0到2*real_m,k从1到n,找到满足条件的k就可以记录到path数组中去,
详情见代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct P
{
int sum,sub;
};
P caipan[201];
int path[21][801],dp[21][801];
bool OK(int a,int b,int c)
{
while(a>0&&path[a][b]!=c)
{
b-=caipan[path[a][b]].sub;
a--;
}
if(a==0)return true;
else return false;
}
int main()
{
int n,m,i,j,k,cas=1,id[21];
while(scanf("%d%d",&n,&m),n+m)
{
memset(caipan,0,sizeof(caipan));
for(i=1;i<=n;i++)
{
int p,d;
scanf("%d%d",&p,&d);
caipan[i].sum=p+d;
caipan[i].sub=p-d;
}
memset(dp,-1,sizeof(dp));
memset(path,0,sizeof(path));
int real_m=m*20;
dp[0][real_m]=0;
for(i=1;i<=m;i++)
for(j=0;j<=2*real_m;j++)
if(dp[i-1][j]>=0)
{
for(k=1;k<=n;k++)
if(dp[i][j+caipan[k].sub]<dp[i-1][j]+caipan[k].sum&&OK(i-1,j,k))
{
dp[i][j+caipan[k].sub]=dp[i-1][j]+caipan[k].sum;
path[i][j+caipan[k].sub]=k;
}
}
for(k=0;k<=real_m;k++)
if(dp[m][real_m-k]>=0||dp[m][real_m+k]>=0)break;
int tmp=dp[m][real_m-k]>dp[m][real_m+k]?(real_m-k):(real_m+k);
//printf("+++%d\n",tmp);
int sum_p=(dp[m][tmp]+(tmp-real_m))/2;
int sum_d=(dp[m][tmp]-(tmp-real_m))/2;
for(i=m,j=0;i>0;i--)
{
id[j]=path[i][tmp];
tmp-=caipan[path[i][tmp]].sub;
j++;
}
sort(id,id+m);
printf("Jury #%d\n",cas++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",sum_p,sum_d);
for(i=0;i<m;i++)
printf(" %d",id[i]);
printf("\n\n");
}
return 0;
}
相关文章推荐
- Jury Compromise(poj 1015)
- POJ 1015 Jury Compromise(dp坑)
- [dp] poj 1015 Jury Compromise
- POJ #1015 - Jury Compromise - TODO: POJ website issue
- POJ 1015 Jury Compromise
- POJ1015-Jury Compromise
- POJ 1015-Jury Compromise动态规划
- poj1015 Jury Compromise
- [POJ 1015] Jury Compromise
- POJ1015-Jury Compromise
- POJ1015 Jury Compromise
- poj 1015Jury Compromise
- poj 1015 Jury Compromise
- POJ 1015 Jury Compromise 2个月后重做,其实这是背包题目
- POJ1015 - Jury Compromise(DP+计算顺序)
- poj 1015 Jury Compromise
- (POJ 1015) Jury Compromise 经典dp问题 (n选m)
- POJ 1015 Jury Compromise
- POJ 1015 Jury Compromise
- POJ 1015 Jury Compromise