奇怪的01背包问题&数组下标平移法(洛谷P2340 [USACO03FALL]Cow Exhibition G)

https://www.luogu.com.cn/problem/P2340

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[800005];
int main()
{
    int n, sav1[405] = {}, sav2[405] = {};
    memset(dp,-0x3f,sizeof(dp));
    dp[400000] = 0;
    scanf("%d", &n);
    for(int i=1;i<=n;++i) scanf("%d%d", &sav1[i], &sav2[i]);
    for(int i=1;i<=n;++i)
    {
        if(sav1[i] >= 0)
        {
            for(int j=800000;j>=sav1[i];--j)
            {
                dp[j] = max(dp[j],dp[j-sav1[i]]+sav2[i]); 
            }
        }
        else
        {
            for(int j=0;j<=800000+sav1[i];j++)
            {
                dp[j] = max(dp[j],dp[j-sav1[i]]+sav2[i]);    
            }//这里因为符号的原因,等效于逆推,因此还是01背包 
        }    
    }
    int ans=0;
    for(int i=400000;i<=800000;i++)
    {
        if(dp[i]>=0)
        {
            ans=max(ans,i+dp[i]-400000);    
        }
    }
    printf("%d", ans);
    return 0;
}

重要思路归纳:

(1)首先明确此题属于01背包

(2)既然是01背包那么就要明确《1》体积《2》价值《3》背包容量

    此处可以选择iq作为体积,eq作为价值

    那么为了考虑所有的情况,背包容量为:-400000~400000

(3)数组下标平移法:
  如上,体积用数组下标表示,因此会出现负数,这个可以用数组下标 平移解决

  即:dp[j]表示iq为j-400000时所拥有的eq值

posted @ 2021-08-02 23:11  Mint-hexagram  阅读(43)  评论(0编辑  收藏  举报