//Accepted 1492 KB 110 ms //背包 //把si看成weight,Fi看成value,这可以表示成当dp[j]=max(dp[j-weight[i]]+value[i]) //考虑到si可能为负,需要整段区间的平移 //背包过程中,根据weight的正负,我们需要考虑dp的顺序,如果weight为正,这j从大到小 //如果weight为负,则要从小到大,这是根据dp[i][j]=max(dp[i][j],dp[i-1][j-weight[i]]+value[i]) //如果我们省略一维,这需要先更新j,再更新j-weight[i],当weight[i]为正时,我们要先更新大的。。。 #include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <cmath> #include <algorithm> using namespace std; /** * This is a documentation comment block * 如果有一天你坚持不下去了,就想想你为什么走到这儿! * @authr songt */ ; ; int value[imax_n]; int weight[imax_n]; ]; int n; int max(int a,int b) { return a>b?a:b; } void Dp() { ;i<=n*;i++) dp[i]=-inf; dp[n*]=; ;i<=n;i++) { && weight[i]<=) continue; ) { ;j>=weight[i];j--) if (dp[j-weight[i]]>-inf) dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } else { ;j<=n*+weight[i];j++) if (dp[j-weight[i]]>-inf) dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } } ; ;i<=n*;i++) ) ans=max(ans,dp[i]+i-n*); printf("%d\n",ans); } int main() { while (scanf("%d",&n)!=EOF) { ;i<=n;i++) scanf("%d%d",&weight[i],&value[i]); Dp(); } ; }