【多重背包】二进制转换/ 其实有区别的--不全懂,会不放心的

2024-02-07 20:38

本文主要是介绍【多重背包】二进制转换/ 其实有区别的--不全懂,会不放心的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

占坑。。。

https://blog.csdn.net/qinzhenhua100/article/details/40350219

啊首先二进制这个,比如7可以化成1  10 100  完美表示。。

6可以是1 10 11(1 2 3  注意是从小到大加  完美表示。。)

多重背包其实就是拆成一个一个去做,由于有些麻烦所有就用二进制代替了,反正组成起来都一样

哇,看了霜雪千年大大的文章(感谢我谷((())))

非常清楚!!!

这人将来一定适合去当老师!!1

https://www.cnblogs.com/acgoto/p/8523258.html

 

关于此题:

代码:

            //那么这个题特殊化到没有重量 并且个数已经先天给好了就是2的c次方减一  
            // 首先 一定都是2的次方减一的话 我们知道可以是直接   01  10  100 。。这种的(所以直接*2就可以了)
            // 其次  价值是v  那么就是2*v  4*v  8*v的组合都可以达到
            //w[i]里面就装的是新转化过之后的体积。
 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
int t,n,q,cnt,x,y,num,c[22],val[500],s;LL dp[10005];
int main(){for(int i=0;i<21;++i)c[i]=(1<<i)-1;while(~scanf("%d",&t)){while(t--){memset(dp,0,sizeof(dp));dp[0]=1;cnt=0;scanf("%d%d",&n,&q);for(int i=1;i<=n;++i){scanf("%d%d",&x,&y),num=c[y];for(int d=1;d<=num;num-=d,d<<=1)val[cnt++]=x*d;if(num>0)val[cnt++]=x*num;}for(int i=0;i<cnt;++i){for(int j=10000;j>=val[i];--j)dp[j]=(dp[j]+dp[j-val[i]])%mod;}while(q--){scanf("%d",&s);printf("%lld\n",dp[s]);}}}return 0;
}

关键代码(雾)

 for(int i=0;i<cnt;++i){
                for(int j=10000;j>=val[i];--j)
                    dp[j]=(dp[j]+dp[j-val[i]])%mod;
            }

 

 

另外,HDU1284  钱币-------------

-----------没有博客园账号,悄咪咪转一下,给出链接 https://www.cnblogs.com/acgoto/p/8523258.html

这个赛时看了,但是这位小老弟怎么回事写的这么简单……………………

以下为复制

Problem Description

在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。

Input

每行只有一个正整数N,N小于32768。

Output

对应每个输入,输出兑换方法数。

Sample Input

2934

12553

Sample Output

718831

13137761

解题思路:这道题可以当做数学题来做。假设某种方案要使用i枚3分硬币(i∈[0,n/3]),那么剩下的就有n-3*i分需要用2分和1分补全。对于2分硬币的个数,可能使用0,1,·····(n-3*i)/2枚,剩下的全都用1分硬币即可。也就是说当使用i枚3分硬币时,就会产生出{(n-3*i)/2+1}*1=(n-3*i)/2+1种方案,那么只要枚举i,将所有方案数相加即可。

-----自己想了一下,的确是,可能使用1是一种,2是一种,……  一直到(。。x)个,大概是因为只有abc三个吧。。。还真爽-。-  只不过别忘记那个0  就是全是1的时候--------

AC代码一:

复制代码

 1 #include<bits/stdc++.h>2 using namespace std;3 int main(){4     int sum,n;5     while(cin>>n){6         sum=0;7         for(int i=0;i*3<=n;++i)8             sum+=(n-i*3)/2+1;9         cout<<sum<<endl;
10     }
11     return 0;
12 }

复制代码

 AC代码二:考虑dp,dp[j]表示用若干个硬币组成钱j的方案数,易得状态转移方程为:dp[j]+=dp[j-i](j>=i),意思是当前币值是i,那么在组成钱j的基础上还可以这样增加新的方案数:用之前的j-i分再和当前i分组成钱j即增加了dp[j-i]*1这么多的方案数。举个栗子:现将3分钱兑换成硬币的所有方案数有①1+1+1=3--->1种;②去掉2枚1分换成1枚2分的硬币1+2=3,那么增加了之前的1种方案数,现共有2种方案数(dp[3]+=dp[3-2]);③还有一种就是用1枚3分的硬币替换3枚1分的硬币3+0=3,定义组成0钱的方案数为1种,那么此时也增加1种方案数(dp[3]+=dp[3-3]),所以组成3分钱共有3种方案数。注意:初始化dp数组全为0,定义dp[0]=1,因为组成钱0(事实上钱0是由钱i-i=0即i=i这种情况得来的)也算一种方案数,然后对于每种币值,从i~最大35000枚举更新累加对应组成钱j的方案数即可。

----------------------自己又想了一下,这个dp理论上说应该和顺序mei有关系啊。

----------------------即使好几个i是一样的,那也是多了一种方案,因为算作的是不同的物品。……

比如,倘若3元兑换,有1种。(1个3)此时dp[0]=1   dp[1]=dp[2]=0

然后1元,dp[1]=1  dp[2]=1  (自己的状态,加上没带i之前的状态/i是新的,即,虽然新来的服务员名字和原来的一样都被叫做了服务员1号但是他们相貌其实是不相同的。。呈现在纸上的只有那个名号。。 他们还是不同的呀)

dp[3]=dp[3]+dp[2]=2(一个是自己的,一个是全1组成的)

然后2 ,dp[1]----  dp[2]=dp[2]+dp[0] (用完了2和之前1组成的那个2)

dp[3]=dp[0]+dp[3]=3... 没有疑问了

 1 #include<bits/stdc++.h>2 using namespace std;3 int main(){4     int n,dp[35000]={1};5     for(int i=1;i<=3;++i)//币值6         for(int j=i;j<35000;++j)//钱j7             dp[j]+=dp[j-i];8     while(cin>>n){cout<<dp[n]<<endl;}9     return 0;
10 }

-------------------

dp这个也很简单,像背包一样,从小到大装,组成方式啊什么的

关键代码。。。

 for(int i=0;i<cnt;++i){
                for(int j=10000;j>=val[i];--j)
                    dp[j]=(dp[j]+dp[j-val[i]])%mod;
        }

 

还有。。。要注意。。。。。。它们是从0转化而来的,所以dp[0]=1 

见过很多次了。。题目里→_→

 

讲道理嘛,下面这样写也可也

https://blog.csdn.net/tianyizhicheng/article/details/82716691  

---------------------------

好了,恭喜我又突破一个境界,看懂了不够,你要搞懂每一个细节。。。那些执行力不够/意志力不够/在很多情况下体现出自卑的人,常常觉得取得了一定的成就就可以了(其实你不写根本 就是理解 的不深刻嘛)(咦谁给我搞成中文标点输入法了。。)恭喜我 继续解锁一个成就  在大人刷抖音小孩玩滑梯放着流行歌曲的kfc比在家效率高写了this。。。。。

   for(int i=1;i<=n;++i){scanf("%d%d",&x,&y),num=c[y];for(int d=1;d<=num;num-=d,d<<=1)val[cnt++]=x*d;//其实可以不必这样,因为给的是2^x-1 肯定除尽。。  可以直接*2 当然这样子写最安全的没错了。。 记得下面这句↓
//原理呢就是分出1减去1分出2进去2 下一个该分4了啊不够了我糖糖一个6只有3分给你  不用怕 你把3拿走吧(就是下面这句剩余价值--虽然本题应该还是用不到)if(num>0)val[cnt++]=x*num;}
// 嘛。物品是这样的,从第一个开始跑i,我们知道;其次,背包要倒着写,最后大于val[x],因为不是完全背包,所以只能加一次
// val这里只要把V乘起来当做一起扩大就可以了。。for(int i=0;i<cnt;++i){for(int j=10000;j>=val[i];--j)dp[j]=(dp[j]+dp[j-val[i]])%mod;}

 

这篇关于【多重背包】二进制转换/ 其实有区别的--不全懂,会不放心的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/688859

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

uva 10130 简单背包

题意: 背包和 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能

多重背包转换成0-1背包

http://acm.hdu.edu.cn/showproblem.php?pid=2191 多重背包特点: 一种物品有C个(既不是固定的1个,也不是无数个) 优化的方法: 运用神奇的二进制,进行物品拆分,转化成01背包 物品拆分,把13个相同的物品分成4组(1,2,4,6) 用这4组可以组成任意一个1~13之间的数! 原理:一个数总可以用2^