这几天主要学习动态规划,首先从01背包问题开始。
从这道题目来看,我之前对01背包理解的还不够深刻,比如说第二层循环中,是逆序还是正序查找,对此我就没有搞清楚。所以在这里反思一下,同时也总结一下这道题。
1。对于最基础的背的体积V 和收益C,我以前总是以为V是作为限制条件出现的,但通过这道题我有所改观,我们可以把V作为转换成本题的SI,C转换成本题的FI,这样,V 就不在是一个限制条件,而是作为表明此时SI的状态,和此在这里面存的数的性质是一样的。
2。就是第二次循环的是逆向还是正向的问题,其实这个问题的本质就是,如种循序能够不重复取,这是01背包区别于完全背包的标志所在。
#include<iostream>
#include<cstdio>
#define min -99999999
using namespace std;
struct cows{
int si,fi;
};
cows s[110];
int dp[200010];
int main(){
int n;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++)
scanf("%d %d",&s[i].si,&s[i].fi);
for(int i=0;i<=200000;i++)dp[i]=min;
dp[100000]=0;
for(int i=1;i<=n;i++){//cout<<i<<endl;
if(s[i].si>0){
for(int j=200000;j>=s[i].si;j--)
if(dp[j-s[i].si]!=min){
dp[j]=max(dp[j],dp[j-s[i].si]+s[i].fi);
// cout<<j<<" "<<dp[j]<<endl;
}
}
else{
for(int j=0;j<=200000+s[i].si;j++)
if(dp[j-s[i].si]!=min){
dp[j]=max(dp[j],dp[j-s[i].si]+s[i].fi);
//cout<<j<<" "<<dp[j]<<endl;
}
}
}
int max1=min;
for(int i=100000;i<=200000;i++){
// cout<<dp[i]<<" ";
if(dp[i]>0&&max1<dp[i]+i-100000)
max1=dp[i]+i-100000;}
if(max1!=min) printf("%d\n",max1);
else printf("0\n");
}
return 0;
}