0-1 Knapsack Problem(背包问题)——关于for(int j=W;j>0;j--)会W掉的解释

博客链接: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]赋值。

所以新机子哇一自摸子多次:数组出界导致的赋值错误就像蝴蝶效应一般影响到答案的正确性。
在这里插入图片描述
所以遇事不决就打印过程,直接手动模拟全过程。

出结论只是时间问题。
在这里插入图片描述
溜了溜了~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值