1.题目描写叙述:点击打开链接
2.解题思路:本题就是经典的01背包问题,i逆序枚举的写法就不介绍了,主要说一下经典的错误写法。假设将输入的n个物品下标设为0~n-1,给出正确的写法和错误的写法。
3.代码:
(正确的写法)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<functional>
using namespace std;
#define me(s) memset(s,0,sizeof(s))
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;
#define rep(i,n) for(int i=0;i<(n);i++)
const int N=1000+10;
int w[N],v[N];
int dp[N][N];
int main()
{
int n,V;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&V);
for(int i=0;i<n;i++)
scanf("%d",&w[i]);
for(int i=0;i<n;i++)
scanf("%d",&v[i]);
me(dp);
for(int i=0;i<n;i++)
for(int j=0;j<=V;j++)
{
dp[i+1][j]=dp[i][j];
if(j>=v[i])
dp[i+1][j]=max(dp[i+1][j],dp[i][j-v[i]]+w[i]);
}
printf("%d\n",dp[n][V]);
}
}
(错误写法一)
for(int i=0;i<n;i++)
for(int j=0;j<=V;j++)
{
if(!i)dp[i][j]=0;
else
{
dp[i][j]=dp[i-1][j];
if(j>=v[i])
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
}
}
printf("%d\n",dp[n-1][V]);
(错误写法二)
for(int i=0;i<n;i++)
for(int j=0;j<=V;j++)
{
if(!i){dp[i][j]=0;continue;}
dp[i][j]=dp[i-1][j];
if(j>=v[i])
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
}
printf("%d\n",dp[n-1][V]);
(错误写法三)
for(int i=0;i<n;i++)
for(int j=0;j<=V;j++)
{
dp[i][j]=(i==0)?0:dp[i-1][j];
if(j>=v[i])
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
}
printf("%d\n",dp[n-1][V]);
以上三种错误写法,假设都明确为什么错了。说明真的理解了状态转移方程。