奇怪的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值