366C - Dima and Salad(0-1 背包)

本文介绍了一种将特定形式的0-1背包问题通过数学转换简化的方法,并利用动态规划求解最优解的过程。针对一组由a[]和b[]构成的数据集,通过引入系数k进行转换得到c[],进而将问题转化为寻找c[]中若干项之和为0且对应的a[]和最大的组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//0-1背包 比赛的时候想到c[i]=a[i]-b[i]*k的转化了 但是没想到用DP
//转化后就是一列数c[]  取其中的任意几个 让它们的和为0 并且所对应的a[]的和最大值
//c[i]的和的范围是-10000到10000
//dp[i][j]表示从前i个数中任意挑出几个数 和为j的状态的所对应a[]的和的最大值
//则dp[n][0]就是从n个数中选出任意个它们的和为0 所对应的a[]的最大值
//但是数组的下标不能是负值  所以把dp[0][10000]当成0点
// 把c[]当成物品体积 a[]当成物品价值




#include<stdio.h>
#include<string.h>


#define max(a,b) a>b?a:b;
int n,k;
int dp[2][21000],a[110],b[110],c[110];


void init()
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);

}
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
c[i]=a[i]-b[i]*k;
}

memset(dp,-1,sizeof(dp));
dp[0][10000]=0;

}


int Dp()
{
int i,j;
int f=0;
for(i=1;i<=n;i++)
{
f=f^1;
for(j=0;j<=20000;j++)
{

if(j-c[i]>=0&&j-c[i]<=20000)
{
dp[f][j]=max(dp[f][j],dp[1-f][j]);//把前一个状态移下来


if(dp[1-f][j-c[i]]!=-1)//0-1 背包
dp[f][j]=max(dp[f][j],dp[1-f][j-c[i]]+a[i]);
}
}

}
if(dp[f][10000])
return dp[f][10000];
return -1;
}
int main()
{
while(scanf("%d %d",&n,&k)!=EOF)
{
init();
int ans=Dp();
printf("%d\n",ans);
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值