博客链接:https://blog.csdn.net/qq_45750296/article/details/109322622
关于为何for(int j=W;j>0;j--)
会使得答案W掉,为了追求真相,我试着将过程打印出来分析一下。
我们先来看一下整体的代码:
#include<bits/stdc++.h>
using namespace std;
int w[105],v[105],dp[10050];
int main()
{
int n,V;
while(cin>>n>>V)
{
for(int i=1; i<=n; i++)
cin>>v[i]>>w[i];
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
{
for(int j=V; j>=0; j--)
{
//if(j-w[i]>=0)
{
printf("判断前:dp[%d]=%d dp[%d-w[%d]]=%d v[%d]=%d\n",j,dp[j],j,i,dp[j-w[i]],i,v[i]); //打印出处理前的相关数据
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("判断后:dp[%d]=%d\n",j,dp[j]); //打印出处理之后的数据
cout<<"--------------------------------------------"<<endl;
}
}
cout<<"i=1时dp数组:"; //将整个dp数组全部输出
for(int j=0; j<=V; j++)
cout<<dp[j]<<' ';
cout<<endl;
cout<<"--------------------------------------------"<<endl;
cout<<"--------------------------------------------"<<endl;
}
cout<<endl;
printf("dp[%d]=%d\n",V,dp[V]);
}
}
这里的dp数组就是f数组,w数组和v数组分别对应c数组与w数组。
我们看一下打印结果的一部分:
(题目中第一个样例作为测试数据)
我们再来看一下用于打印AC代码中dp数组信息的代码:
#include<bits/stdc++.h>
using namespace std;
int w[105],v[105],dp[10050];
int main()
{
int n,V;
while(cin>>n>>V)
{
for(int i=1; i<=n; i++)
cin>>v[i]>>w[i];
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
{
for(int j=V; j>=w[i]; j--)
{
printf("判断前:dp[%d]=%d dp[%d-w[%d]]=%d v[%d]=%d\n",j,dp[j],j,i,dp[j-w[i]],i,v[i]); //打印出处理前的相关数据
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("判断后:dp[%d]=%d\n",j,dp[j]); //打印出处理之后的数据
cout<<"--------------------------------------------"<<endl;
}
cout<<"i=1时dp数组:"; //将整个dp数组全部输出
for(int j=0; j<=V; j++)
cout<<dp[j]<<' ';
cout<<endl;
cout<<"--------------------------------------------"<<endl;
cout<<"--------------------------------------------"<<endl;
}
cout<<endl;
printf("dp[%d]=%d\n",V,dp[V]);
}
}
看一下同样的样例产生的打印结果:
通过对比我们可以发现:
当i=1,j=1时,此时按照正常来说,我们无法将1号物品放入j=1的背包中,所以此时dp[1]=0(如同2号代码打印结果)。
可是由于1号代码中并没有判断j-w[i]
是否为有效数字(此时j-w[i]=-1
,而dp[-1]是一片未知区域),导致程序出错,错给dp[1]赋值。
所以新机子哇一自摸子多次:数组出界导致的赋值错误就像蝴蝶效应一般影响到答案的正确性。
所以遇事不决就打印过程,直接手动模拟全过程。
出结论只是时间问题。
溜了溜了~