#動態規劃#Poj 2184 Cow Exhibition

#include <iostream>
#include <cstring>

#define INF 0x3f3f3f
 
using namespace std;

//目標:尋找揹包容量與價值。
//已知:智商+幽默感(看似都是屬性,咋整?)  但是0-1揹包的特徵很明顯,對每頭牛,取or不取,那每頭牛肯定是一個價值量

//兩個屬性,一個做容量,另一個做價值。 最後加判斷求和。 
//https://blog.csdn.net/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.csdn.net/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;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章