01背包 空间优化O(N)版本
#include<stdio.h>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
struct coin
{
int v;
int w;
}list[505];
int dp[10005];
int main()
{
int e,f;
while(scanf("%d%d",&f,&e)!=EOF)
{
for(int i=1;i<=e;i++)
{
scanf("%d%d",&list[i].w,&list[i].v);
}
//背包不用恰好装满 普通初始化
for(int i=0;i<=f;i++)
{
dp[i]=0;
}
//尽管是一维的空间优化版本 但是依然得按照从第个一物品到最后一个物品的顺序考虑添加到包里
//外层循环不能少
for(int i=1;i<=e;i++)
{
//背包容量遍历顺序区别于完全背包
//01背包中的 dp[j-list[i].w] 是历史状态
//01背包必须倒叙遍历 防止破坏历史状态 因为每种物品就1件 要不拿要不不拿 考虑第4件物品时 第三件物品的dp记录已经算是历史状态
//如果01背包空间优化版本正序遍历了 ,那历史状态会都被破坏因为dp[i..]=dp[i-1..],为了保留历史状态 所以必须倒叙遍历
//完全背包要正序遍历 因为每种物品数量无限 要改变现在状态 容量正序遍历正好是改变现在状态的情况
for(int j=f;j>=list[i].w;j--)
{
//普通01背包不同加判断历史可不可到达,但是恰好装满的01背包必须需要判断历史情况是否可到达
dp[j]=max(dp[j],dp[j-list[i].w]+list[i].v);
}
}
printf("%d\n",dp[f]);
}
return 0;
}