2 条题解

  • 3
    @ 2022-11-24 16:25:58

    虽然01背包时间复杂度几乎无法再优化,但我们可以优化空间复杂度,也就是把f数组压成一维的 那么我们现在如何用一维数组f[0...j]得到? 事实上,我们只需要将v倒推即可,不过与无优化的不同的是,由于我们把f[i]定义为不超过v公斤的最大价值,那么我们要把v推到从w[i]即可,之后由于放不进去了,所以我们无需继续循环 那么此时状态转移方程为f[i]=max(f[i],f[v-w[i]]) (v>=w[i],i:1-n)

    #include<bits/stdc++.h>
    using namespace std;
    int dp[1001],w[1000],v[1001];
    int main()
    {
    	int m,n; 
    	scanf("%d%d",&m,&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&w[i],&v[i]);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=m;j>=w[i];j--)//dp表示重量不超过j的最大价值 
    		{
    			dp[j]=max(dp[j],dp[j-w[i]]+v[i]);//状态转移方程其实等效于01背包,只不过变了形式 
    		}
    	}
    	cout<<dp[m];
    	return 0;
    }
    

    那个……由于更新时间过长,所以这两篇表述时的数组或变量名可能与我的程序不符qwq

    • 3
      @ 2022-11-24 16:15:54

      w[i]是体积,c[i]是价值 用f[i][j]定义当第i件物品时背包容量为j时的最优解 那么最终答案就是f[n][m] 那么当第i件物品能被放入空间为j时的背包中时 f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])(i:1-n,j:m-1) 如果第i件物品放不到容量为j的背包中时,我们直接考虑继承,即f[i][j]=f[i-1][v]; 那么我们的状态转移方程就出来了,如上 那么程序也就解决啦~

      #include<bits/stdc++.h>
      using namespace std;
      int dp[1001][1001];//用来存储第i件物品,背包空间为j的最大值 
      int w[1001],v[1001];//重量+价值 
      int main()
      {
      	int m,n;
      	cin>>m>>n;
      	for(int i=1;i<=n;i++)
      	{
      		scanf("%d%d",&w[i],&v[i]);
      	}
      	for(int i=1;i<=n;i++)
      	{
      		for(int j=m;j>=1;j--)//倒推 
      		{
      			if(w[i]<=j) dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);//如果能放得下,就有两种选择:1,不放,此时f[i][j]=f[i-1][j](前一件的状态)2,放,那么放下去之后背包所剩空间等于j-w[i],f[i][j]=f[i-1][j-w[i]];综上,dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) 
      			else dp[i][j]=dp[i-1][j];//如果放不下就没得选喽,只能是前一件的状态了 
      		}
      	}
      	cout<<dp[n][m];//输出最优 
      	return 0;
      }
      
      • 1

      信息

      ID
      462
      时间
      1000ms
      内存
      256MiB
      难度
      6
      标签
      递交数
      114
      已通过
      31
      上传者