3 条题解

  • 0
    @ 2022-1-17 20:30:08
    
    /*
    数量太多,朴素的做k次01背包就复杂度过高
    因为做了很多重复性工作,有些选取是等效的 
    这里采用二进制分组的方式拆分优化该问题
    例如6个物品拆成1 2 3 3组,那么该3个数字 
    的任意组合就可以凑出1到6的所有数字了(不重复选取)。
    所以转化为01背包问题
    对于每一个物品个数:
    一直拆成2的次方个,如果不够了,就单独在列一组即可
    回到这道题,最多有2000个,2的10次方就是1024,最多估计有个10组
    所以v,w这里定义大小是10000. 
    */ 
    #include<bits/stdc++.h>
    using namespace std;
    int N,V,v[10005],w[10005],f[2005],v1,w1,m1,cnt;
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cin>>N>>V;
    	for(int i=1;i<=N;i++)
    	{
    		cin>>v1>>w1>>m1;//体积,价值,个数 
    		int c=1;//从1开始 
    		while(m1-c>0)//能拆就一直拆 
    		{
    			m1-=c;
    			v[++cnt]=c*v1;
    			w[cnt]=c*w1;
    			c*=2;//每拆一次去乘以2 
    		} 
    		v[++cnt]=m1*v1;//拆不动了剩下的单独拿一组 
    		w[cnt]=m1*w1;
    	}
    	for(int i=1;i<=cnt;i++)//一共cnt个物品做01背包 
    	{
    		for(int j=V;j>=v[i];j--)
    		{
    			f[j]=max(f[j],f[j-v[i]]+w[i]);
    		}
    	}
    	cout<<f[V];
        return 0;
    }
    • -3
      @ 2022-4-24 19:00:05

      写题解请注意

      鼓励大家写题解,但注意题解格式。

      题解一定要有思路解析或代码注释,能否让别人理解你的思路

      也是你的能力的检验,不要只放无意义的代码给大家复制,那就失去了做题的初心。

      给代码两端加上这个会舒服一些

      ```cpp

      你的代码

      ```

      </span>

      这个点在键盘的左上角tab上面那个键,注意切换输入法

      #include<iostream>
      using namespace std;
      int main()
      {
          int n;
          cin>>n;//这是一个注释
          return 0;
      } 
      

      请注意严禁抄袭题解,写题解不要只放代码,需加上你的思路或代码注释。

      抄袭题解一经发现直接取消成绩。

      题解被删除的可能

      1. 代码不符合格式规范
      2. 没有思路讲解或者没有注释,
      3. 无意义的题解

      大家携手共同维护一个良好的编程环境,如果一经发现,多次作乱。可能会被管理员拉黑,请注意,一旦拉黑即失去登陆资格。

      • -3
        @ 2022-4-19 22:28:02

        严禁抄题解,发现后取消成绩

        • 1

        信息

        ID
        885
        时间
        1000ms
        内存
        128MiB
        难度
        5
        标签
        递交数
        53
        已通过
        19
        上传者