概述:

看完题目大家应该就会想到这题可以用一个组合数的思路去编写代码。也就是说我们从给出的一个数组中去随机地抽取中若干个数相加,相加的和要等于给出的那个数。虽然大致思想是没错了,但是,具体的思路是怎么样的呢?

思路分析:

我们是不是会有一种通用的方法来得到一维数组,用来告诉计算机,这个一维数组的某一个位置是我要选取的数呢?

可能大家都会想到的是递归,不过我一个朋友给了我另一个思路,那就是用位移来解决这个问题。为什么用位移,因为快!

这里面有一个小技巧,那就是1<<n是等于2的n次方(例如1<<5 = 32)。也就是说把1左移n位,这里会得到一个结果,这个结果就是我们这个一维数组全部的子集,也就是全部的组合数。

其实如果你了解数字在计算机中的存储和递增过程,那么你就会得到一个有趣的结论,那就是我从0(空集)到1<<n这些数代表的就是我们要告诉计算机在那些位上是我们需要留下的,那些位上的数是我们不需要的。关于数字在计算机中的存储和递增过程这里不作讲解。有兴趣的朋友可以去查阅相关资料。

以上只是得到了全部的组合数。而他们也都是单个数字代表的,那我们能不能通过某种操作或是计算来获得一个标志数组或是某他的什么东西来说明,当前数组的第i位是需要的呢?因为单是一个数字代表的某种组合还不能让计算机完全理解,我们需要的是哪个位置的值。

下面我们假设有一个数字5,那我们应该怎么得到这个数字5所代表的组合呢?

0 1 0 1
0 0 0 1

上面的表格的第一行是数字5,第二行是数字1.

我们现在假设题目中告诉我们的是只有4个数。

那么,我们先得到a&1的值(&是位且操作符,它的作用是当两个数的每个二进制位的值都是1时,该位的值才是1,。。。。。。。想知道具体的,请查阅资料)。

这样,我们由第一个表格就可以得到一个数字1,我们把它保存在b[0]中。

这时,a右移a>>1 = 0010b

0 0 1 0
0 0 0 1

同理,这时b[1] = 0

a右移a>>1 = 0001

0 0 0 1
0 0 0 1

b[2] = 1

a右移a>>1 = 0000

0 0 0 0
0 0 0 1

b[3] = 0

a的位移结束。。。这时我们就得到了一个一维数组b[] = {1, 0, 1, 0};

我们可以看到它就是我们的a的二进制的逆序,如果你不喜欢逆序,那就用自己的方式获得正序的数组。

关于a的位移关键代码:

private static int[] getBitShift(int a, int n) {int[] bit = new int[n];for (int i = 0; i < n; ++i) {bit[i] = a&1;a >>= 1;}return bit;}

-------------------------------------------- 完整 AC CODE -----------------------------------------

import java.util.Scanner;public class Main {private static final int N = 4;/*** 通过位移得到一个组合数的一维数组* @param a* @param n* @return*/private static int[] getBitShift(int a, int n) {int[] bit = new int[n];for (int i = 0; i < n; ++i) {bit[i] = a&1;a >>= 1;}return bit;}/*** 得到某个bit数组所对应的sum值* @param bit* @param datas* @return*/private static int getBitShiftSum(int[] bit, int[] datas) {int sum = 0;for (int i = 0; i < datas.length; i++) {if (bit[i] == 1) {sum += datas[i];}}return sum;}/*** 得到整个数组中共有多少个这样的组合数* @param datas* @param t* @return*/private static int getCount(int[] datas, int t) {int count = 0;for (int i = 0; i < (1 << datas.length); ++i) {int[] bit = getBitShift(i, datas.length);if (getBitShiftSum(bit, datas) == t) {count++;}}return count;}public static void main(String[] args) {Scanner input = new Scanner(System.in);int n = input.nextInt();int t = input.nextInt();int[] datas = new int[n];for (int i = 0; i < n; i++) {datas[i] = input.nextInt();}System.out.println("" + getCount(datas, t));}
}

这里再给出我另一篇博客,《用递归和位移进行枚举子集合》这里是介绍了用递归和位移两种方法进行枚举子集合的过程,感兴趣的朋友可以去看看。。。

点击连接进行查看。

POJ-4004:数字组合(用位移方法解组合数问题,Java版)相关推荐

  1. php正则大小写字母,php 常见email,url,英文大小写,字母数字组合等正则表达式详解...

    操作符 描述 \ 转义符 (), (?:), (?=), [] 圆括号和方括号*, +, ?, {n}, {n,}, {n,m} 限定符 ^, $, \anymetacharacter 位置和顺序 | ...

  2. php正则字母大小写,php 常见email,url,英文大小写,字母数字组合等正则表达式详解...

    操作符 描述 \ 转义符 (), (?:), (?=), [] 圆括号和方括号*, +, ?, {n}, {n,}, {n,m} 限定符 ^, $, \anymetacharacter 位置和顺序 | ...

  3. 方法的重载---(Java版)

    简言:首先,我们要明白的是,我们为什么要学方法的重载? 我们要先思考这样的一个问题. 解答:因为我们在进行项目的开发当中,我们把要实现的功能基本一致,基本相似的方法时,我们给方法会给出相同的方法名,但 ...

  4. Bailian4004 数字组合【递归+DP】

    4004:数字组合 总时间限制: 1000ms 内存限制: 65536kB 描述 有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式.如: n=5,5个数分别为1,2,3,4,5,t=5: ...

  5. Android 蓝牙开发(扫描设备、绑定、解绑)Kotlin版

    Kotlin版 蓝牙开发 (扫描设备.绑定.解绑) 前言 运行效果图 正文 ① 配置项目 ② 布局和样式 ③ 编码 1. 通知栏样式修改 2. 蓝牙设备列表适配器编写 3. 权限请求 4. 初始化蓝牙 ...

  6. python有四个数字_Python生成0-9任意4位数字组合的方法

    玩蛇网本文是关于Python生成0-9任意4位数字组合的方法示例.0-9个数字组成任意4位数字,有多少种排列组合的方式,要是用想的需要不少时间而且还容易出错.用python方法来解决这个问题显然简单得 ...

  7. 号称全网最全CAD组合键功能详解

    左手键盘右手鼠标,一向都是大家熟悉的使用CAD的操作方式. 就算不信手拈来也基本了然于心. 然而如果现在问你,命令行隐藏了,应该怎么调用出来,你可以第一时间反应过来是什么组合键吗? 暂时忘记没关系,希 ...

  8. LintCode 数字组合 题解

    数字组合 描述 笔记 数据 评测 给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T.C中的数字可以无限制重复被选取. 例如,给出候选数组[2,3,6,7]和目标数字7,所 ...

  9. 【卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10)】

    卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10) 在上一章已经完成了卷积神经网络的结构分析,并通过各个模块理解 ...

最新文章

  1. 详细解说 STL 排序(Sort)
  2. java多线程系列(四)---ReentrantLock的使用
  3. QT的QGraphicsView类的使用
  4. 使用phpmaill发送邮件的例子
  5. 技术分享 | 微服务模式下如何高效进行API测试
  6. 链表之单、双链表反序
  7. android 圆角按钮渐变,Android实现圆形渐变加载进度条
  8. 怎样让计算机恢复到桌面上,如何把电脑桌面恢复成原样.怎么办?
  9. “约见”面试官系列之常见面试题之第一百零六篇之css只在当前组件中起作用(建议收藏)
  10. linux phpstudy
  11. 又被野外利用了!新曝光Office产品多个远程命令执行漏洞分析
  12. stm32实验报告心得体会_嵌入式第9次实验报告
  13. Log4J日志配置详解3
  14. 21天学通JAVA:类的定义和对象的创建
  15. ERP系统如何完成工厂车间流程
  16. 第一章 引论 -- 项目管理知识体系指南(PMBOK指南)(第五版)
  17. Kubernetes1.3:QoS服务质量管理
  18. 虚拟内存设置调整图解
  19. 计算机课堂教学改革培训心得体会,课堂教学改革心得体会范文(精选6篇)
  20. 你会使用Excel中的【照相机】吗?

热门文章

  1. 深度探索C++ 对象模型(2)-类的对象的内存大小_2
  2. 初等数论--整除--判断一个数是否是素数
  3. linux kernel中的进程栈
  4. 通过系统调用open来查看flag
  5. Python中*args 和**kwargs的用法
  6. 爬虫Selenium报错“cannot find Chrome binary“解决方案
  7. 2021暑假每日一题 【week6 完结】
  8. 【PAT乙级】1049 数列的片段和 (20 分)
  9. 牛客2021年愚人节比赛 【题解】
  10. 2.1.3 字符与字符串