HDU3496
已空间优化
疑惑点在 dp[时间][看电影数量]的初始化问题上面
dp[0][0]=0。。。。是吧
dp[0][i]=-inf,,,,,,,这个-inf一定要足够大,题目中的数据是输出的最大价值是<2^31 LL 在dp[0][i]更新的时候,最后是dp[0][i]+总和val,那这儿的-inf肯定是要足够足够大 最后才保证dp[0][i]在更新的时候,选取最大值时才取不到这个不合理的值
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#define X 1005
using namespace std;
int dp[X][X];
int main()
{
int t;
cin>>t;
while(t--)
{
int N,M,L;
int w[X],v[X];//L分钟看动画片
scanf("%d%d%d",&N,&M,&L);
for(int i=0;i<N;++i)
{
scanf("%d%d",&w[i],&v[i]);
}
for(int i=0;i<=L;++i)
for(int j=0;j<=M;++j)
{
if(j==0)
dp[i][j]=0;
else
dp[i][j]=-1000;
}
for(int i=0;i<N;++i)
{
for(int j=L;j>=w[i];--j)
{
for(int k=M;k>=1;--k)
{
dp[j][k]=max(dp[j][k],dp[j-w[i]][k-1]+v[i]);
}
}
}
if(dp[L][M]<0)
dp[L][M]=0;//
cout<<dp[L][M]<<endl;
}
return 0;
}
HDU2184
看出来是一道二维01背包问题
可是怎么确定背包的容量是多少呢?
wa证明我的二维01背包思路是错误姿势
自己写不出来二维01背包实现的,看了网上的题解都是对滚动数组进行分析加上对背包容量的固定偏移量来实现好菜,
滚动数组的正序及逆序:
深入一下滚动数组吧,可以把样例中的负值全部都转化为正直,然后用画表格的方式走一遍滚动数组在实现的时候是怎么样把当前第i件物品更新到dp里面的
(手动实现)这时候每个背包的容量下对应的物品都是放入一次的(空间优化的逆序放入过程),可是存在负值的时候就对应的不同种容量的背包状态是对应得一件物品得多件(自然就不是01背包了)
然后就有了题解中大神理解得对占用负的容量的 一个正序更新dp数组过程(也是自己手动模拟过程,我模拟了一遍)
没有给出背包容量转化为用一定的偏移量来代替没有给出的容量:
因为数据最小负值为-1e5 最大值1e5,那么dp更新范围在2e5之间,所以可以用2e5代表最大的容量,容量最小的基数为1e5,避免出现-1e5的数据使数组访问越界
(原先写得初始化思路:题目使容量尽量大,所以初始化为-inf d[1e5]就代表了01原型背包中的dp[0],((感觉是错误得因为,这道题本身就是含有负值,搞为0得话,就会导致含有一个负值很大得时候他永远不会被选中
((感觉是这样(⊙﹏⊙)
再有的细节就是对于两个数据都是<0肯定不会选中,所以可以直接跳过。
参考
#include <bits/stdc++.h>
#include <iostream>
#define X 10005
#define inf 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
const ll moad=1e9+7;
const int maxn=1e6+10;
int dp[maxn];
int w[maxn];
int c[maxn];
int vis[maxn];
int Max=2e5;//固定偏移量
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;++i){cin>>c[i]>>w[i];if(c[i]<=0&&w[i]<=0)--i,n--;}
for(int i=0;i<=Max;++i) dp[i]=-inf;
dp[100000]=0;
for(int i=0;i<n;++i)
{
if(c[i]>=0)
{
for(int j=Max;j>=c[i];--j)
if(dp[j-c[i]]>-inf)
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
if(c[i]<0)
{
for(int j=0;j<=Max+c[i];++j)
if(dp[j-c[i]]>-inf)
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
}
int ans=0;
for(int i=1e5;i<=Max;++i)
if(dp[i]>0&&(dp[i]+i-Max/2)>ans)
ans=dp[i]+i-1e5;
cout<<ans<<endl;
}
return 0;
}