试题 算法训练 无聊的逗

资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中。不过他想到了一个游戏来使他更无聊。他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的情况下长度最长是多少。

输入格式

第一行一个数n,表示n个棍子。第二行n个数,每个数表示一根棍子的长度。

输出格式

一个数,最大的长度。

样例输入

4
1 2 3 1

样例输出

3

数据规模和约定

n<=15n<=15n<=15

题解

思路

在这里我们最容易想到的解法就是枚举每一种情况来进行暴力求解,比较数据本身范围也不大

但是现在的难点在于如何表示某一种选木棒的情况,这时候就可以用二进制来进行存储了。

相信大部分同学的教务系统是有查询空教室的功能的,而这个查询空教室是可以选择任意周-星期-节次的任何排列的,他的原理就是用到了二进制

我们可以将一个数转化为二进制,而他二进制的每一位的1表示选,0表示不选,就比如说在这道题中,假设有四个木棍,我们选择第一个和第三个木棍,那么我们就可以将这种选择表示成二进制的0101.

而选择这两个木棍以外的其他所有木棍的情况就可以表示成1111-0101=1010

其次,我们想要判断一种选择的组合是否选择了某一个木棍a,我们只需要将这个木棍单独取出作为一种选择情况1<<(a−1)1<<(a-1)1<<(a−1),比如我选择了第二个木棍,那就是1<<(2−1)1<<(2-1)1<<(2−1)=0010.接着,我们将这种情况和要判断的选择组合进行按位与操作,如果结果为0说明当前选择没有选到这个木棍.

比如,1000这种选择情况,我们需要判断它是否选择了第二个木棍,那么我们只需要进行1000&00101000\&00101000&0010这个运算,可以得出000000000000=0,这时候我们就知道这种选择情况并不包含第二个木棍。

反之,1010这种情况,1010&0010=0010=2≠01010\&0010=0010=2\not=01010&0010=0010=2​=0,那这种选择情况是选择了第二个木棍的

接着再来说说,移位运算,比如1=0001,当他进行移位操作时,向左移两位,也就是1<<21<<21<<2,得出来的结果就是000100=0100000100=0100000100=0100也就是相当于1∗221*2^21∗22,但是使用移位运算可以大大降低时间复杂度

还有,在下面一个代码中比较难理解的地方,就是对于两个木棍的序列,为什么第二个序列的排列情况需要跟第一个序列进行按位与操作,这个倒也不难解释

首先,假设我们序列1选择了2,3两个木棍,也就是00110,但是我们序列2枚举的是3,4,5三个木棍(11100),我们会发现存在一个木棍3重复使用了,这种情况肯定是不存在的,所以我们肯定要把第二个序列的木棍3去掉,想去掉,我们写循环加判断明显是太麻烦了,而且时间复杂度很高,所以我们可以使用按位与运算:假设我们现在2,3这两个棍子已经拿走,那么序列2只能选择(11001)这里面的木棍,我们将“可供选择的木棍列表”和“当前枚举的木棍序列2”进行按位与:11001&11100=1100011001\&11100 = 1100011001&11100=11000,神奇不?是不是把多与的木棍3去掉了?

这个原理比较好理解,我们可以理解为,对于每一个木棍(也就是二进制的每一位),如果我当前有剩下的,并且我选到了他,那么我就把他选下,如果没有,我就不选他。

注释很全,多揣摩揣摩吧~

代码

package com.lanqiao;import java.util.Scanner;/*** @author 王宇哲*/
public class 算法训练_无聊的逗 {static int n;static int[] nums;/*** 最长的相同木棍长度*/static int maxLength = Integer.MIN_VALUE;/*** 存储某种排列组合下木棍的长度*/static int[] length;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);n = scanner.nextInt();nums = new int[n];//对于n个木棍,共有2^n种排列组合方式length = new int[1<<n];for(int i=0;i<n;i++){nums[i] = scanner.nextInt();//1<<i表示的下标指的是只选第i根木棍的长度length[1<<i] = nums[i];}//遍历存储每一种选择方式的长度,i=1的情况for(int i = 0;i < ( 1 << n ); i++){//这一层遍历是用来选择木棍的for(int j = 0;j < n;j++){//如果i这种情况和选择木棍j有冲突,也就是第i种选择方式并没有选择第j跟木棍//举个例子,比如i为4,二进制就是100,但是j为0,也就是选择了第1根木棍//此时 1<<j = 001  那么第i种情况明显没有选择木棍j,所以他们进行按位与运算的结果就是0//因此这种情况出现冲突,不用进行运算if((i & (1<<j) ) == 0){continue;}//如果这种情况考虑在内了,那么第i种情况的长度就是木棍j的长度加上情况i不选择木棍j的长度//还是举个例子//比如目前i是5,也就是101,j是2,也就是第三根木棍,此时1<<j = 100,//那么第i种组合的情况其实就是i = 001 时的长度加上木棍j的长度length[i] = length[i - (1<<j)] + nums[j];//这个break是用来防止重复计算的break;}}//枚举每一种情况ifor(int i=0;i< (1 << n);i++){//j就是选出了所有情况i没有选择的木棍的情况,(1<<n) -1指的是选择了所有木棍的一种情况//1<<n 就是第n+1位为1,其余每一位为0,比如n=5时,表示100000,//1<<n - 1 就是从1到第n位每一位都为1,比如n=5时,表示的就是11111;//(1<<n) - 1 -i 就是选择了所有i没有选择的木棍的情况,比如n=5,i=3//那么(1<<n)-1 = 11111,i=00011,那么(1<<n) - 1 -i = 11100int j = (1 << n) -1 -i;//接下来的循环是尝试从选择了全部i没选的木棍的情况开始枚举//枚举每一种可能的选择情况,k--会存在不合理的数据,比如说现在剩下的木棍是11000,而k当前枚举到的实是10000,//那么此时k-- = 01111,后面会多出三个木棍,所以我们需要使用按位与来去除多余的木棍,for(int k = j;k > 0;k = (k-1)&j){if(length[k] == length[i]){maxLength = Math.max(maxLength,length[k]);}}}System.out.println(maxLength);}}

蓝桥杯算法训练 无聊的逗-详细注释版相关推荐

  1. 蓝桥杯算法训练 无聊的逗(状态压缩搜索)

    试题 提交此题   评测记录 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n ...

  2. 蓝桥杯 算法训练 无聊的逗

    题目描述 问题描述 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在 ...

  3. 蓝桥杯 算法训练 无聊的逗 python

    资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一 ...

  4. 蓝桥杯 算法训练 强力党逗志芃

    蓝桥杯 算法训练 强力党逗志芃 题目描述 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 逗志芃励志要成为强力党,所以他将身上所以的技能点都洗掉了重新学技能.现在我们可以了解到,每个 ...

  5. 蓝桥杯算法训练-强力党逗志芃

    持续更新蓝桥杯算法训练题解,有兴趣可以关注一波呀 题目 逗志芃励志要成为强力党,所以他将身上所以的技能点都洗掉了重新学技能.现在我们可以了解到,每个技能都有一个前提技能,只有学完了前提技能才能学习当前 ...

  6. 蓝桥练习---------算法训练 无聊的逗

    问题描述 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长 ...

  7. 【蓝桥杯 算法训练】强力党逗志芃

    题目 题目链接 蓝桥杯 算法训练 强力党逗志芃 思路: 树形dp 定义状态: dp[i][j]表示以i为根,消耗j个技能点,最多能换取的v 状态转移方程: dp[pos][k]=max(dp[son] ...

  8. 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解 - 未完善

    题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...

  9. 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解

    题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...

最新文章

  1. TIOBE 新榜单:Python 超越 Java 重回第二,Rust 崛起
  2. HBase解决Region Server Compact过程占用大量网络出口带宽的问题
  3. CoordinatorLayout 使用及源码解析
  4. Java静态变量注入配置值,工具类使用@Value将信息注入到静态变量中
  5. 【Drools三】打工人学习Drools高级语法
  6. (40)FPGA面试技能提升篇(OAM与SDH协议)
  7. vue 渲染函数处理slot_Vue源码全面解析七 initRender 函数(处理渲染相关的函数)...
  8. blender php,Blender 源码学习 --- Modifier
  9. 2015与2016年终总结
  10. LeetCode之移除元素
  11. ZFAKA最新版最简安装教程
  12. SPSS导入excel文件时,保留4位小数点
  13. matlab钢琴音教程,手把手教你钢琴基本指法(有图有真相,通俗易懂,钢琴入门必备)...
  14. 珍大户 认知世界的经济学 经济学核心原理 思维导图
  15. Android 中关于九宫格图片的那些事
  16. 月入万元或不需缴税!九张图带你看懂个税新规
  17. 比特位操作之ffs和fls实现原理
  18. 如何使用 K8s 实现跨集群管理,这篇文章告诉你了!赶紧收藏
  19. 中断号 和 中断向量区别
  20. 贝索斯宣布“退位”,去追寻“诗和远方”

热门文章

  1. 我们社会的普遍价值观 2012-01-10 22:31:27
  2. iOS网络请求错误nw_proxy_resolver_create_parsed_array PAC evaluation error: NSURLErrorDomain: -1004
  3. php编写文件管理工具,php之markdown文档管理工具的实现代码
  4. Rsync备份工具讲解(一)
  5. FFMPEG AV sync
  6. 大数据融合:提高社会治理社会化、法治化、智能化、专业化水平
  7. S2B2C商城系统(分销商城)哪家好?S2B2B商城系统好在哪?
  8. 被“豢养”的中国科技
  9. kali metasploit 制作后门程序远程操控基本使用方法
  10. Educoder/头歌JAVA——CSS从入门到精通——基础知识