#动态规划#Poj 2184 Cow Exhibition

本文深入探讨了0-1背包问题的复杂变种,通过解析一段代码,详细讲解了如何处理具有双属性(如智商与幽默感)的物品,将其转化为背包问题并求解最优解的过程。文章涵盖了动态规划的实现细节,包括初始化、状态转移方程及最终结果的计算。

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

#include <iostream>
#include <cstring>

#define INF 0x3f3f3f
 
using namespace std;

//目标:寻找背包容量与价值。
//已知:智商+幽默感(看似都是属性,咋整?)  但是0-1背包的特征很明显,对每头牛,取or不取,那每头牛肯定是一个价值量

//两个属性,一个做容量,另一个做价值。 最后加判断求和。 
//https://blog.youkuaiyun.com/Tc_To_Top/article/details/49871783
const int mid = 100000;
const int N = 110;
int ts[N];
int tf[N];
int dp[mid*2+10];
 
int n;
int main(){
	scanf("%d",&n);
	
	for(int i=0;i<n;i++){
		scanf("%d %d",&ts[i],&tf[i]);
	}
	
	memset(dp,-INF,sizeof(dp));//因为有负数,所以初始化为一个很小的负数 
	dp[mid]=0;//起点为0
	
	for(int i=0;i<n;i++){
		if(ts[i]>0){
			for(int j=mid*2-1;j>=ts[i];j--){//j>=ts[i]的意思是能放的下开ts[i] 
			//直接从mid*2-1开始遍历,怎么就说明挪了100000个位置呢?
			// 联想一下最普通的0-1背包,那个是从容器最大值开始遍历,这个的最大值变成什么呢?变成200000(i是dp下标,表示的是容量,即ts的和,范围是-100000~100000) 
				dp[j]=max(dp[j],dp[j-ts[i]]+tf[i]);
			}
		}else{//ts[i]<0时正序遍历,因为j-ts[i]此时大于0了,从表格上来看,就是上面行的更新需要下面行的原始数据,所以正着遍历,后面的行还是原始数据没有变。
		//https://blog.youkuaiyun.com/dr5459/article/details/9220563 
		
			//体积总和也是有上下限的,可以在上面输入的时候就求出来。 
			//一个0-1背包,一个完全背包???????????????????????????????????????????????????
			//https://www.2cto.com/kf/201508/427415.html    对称的,正负在坐标轴上关于原点对称? 
			//int j = S[i]; j - S[i] < mid*2; ++j    为啥呢? j减去ts[i],剩下的范围小于总的,也就是ts[i]没把全部范围用掉?
			//好像不是这么理解, 
			
			//其实用范围这一说可以理解,上面ts[i]为正时,是所有可能影响的都要包括,而这里可能影响的范围变了,因为ts[i]是负的,下面的减减相遇是加,上面范围自然就更小,是为s[i]空出来的。 
			for(int j=0;j<=mid*2+ts[i];j++){//为什么要+ts[i]??????????????????????????????????????????????????? 
			//注意dp范围,所有可能影响的都要包括(https://www.cnblogs.com/kuangbin/archive/2012/09/14/2684929.html) 
			//可能受ts[i]影响的, 
				dp[j]=max(dp[j],dp[j-ts[i]]+tf[i]);
			}
		}
	} 
	
	int ans=0;
	for(int i=mid;i<mid*2;i++){//从mid开始 ,因为mid之前是负数,不考虑。 
		if(dp[i]>=0){//必须有这个判断,为什么?因为有的dp还是初始化的-inf 
			ans = max(ans,dp[i]+i-mid);//i-mid就是ts的原始值 
		} 
	}
	printf("%d",ans);
	
	
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值