无聊的逗(二进制法)

2024-03-30 01:18
文章标签 二进制 无聊

本文主要是介绍无聊的逗(二进制法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

c++版

#include<iostream>
#include<algorithm>
#include<cmath> 
using namespace std;
int main()
{int n;//n个木棍 每根的长度 cin>>n;int length[20]={0};//存每个木棍的长度 int number[1<<n]={0};//存储每一种组合方式的总长度  难道是因为没有初始化的原因?? 数组初始化很重要for(int i=0;i<n;i++){cin>>length[i]; number[1<<i]=length[i]; //只有一根木棍的时候的长度 也是一种组合情况 //移位是表示用了第几根木棍 }for(int i=0;i<(1<<n);i++) //遍历每一种组合方式  i=0 空集也是一种组合方式 {for(int j=0;j<n;j++)//每一种木棍的情况 {if((i&(1<<j))==0)//没有重合的木棍  因为j是10进制 i是二进制 1<<j把转换成二进制就能知道当前是取的哪个木棍了 {continue;}number[i]=number[i-(1<<j)]+length[j];//存入该组合的排列长度 break;}}int MAX=0;for(int i=0;i<(1<<n);i++){int j=(1<<n)-1-i;//用总的组合- i当前的排列 就是除了i的其他所有的组合for(int k=j;k>0;k=(k-1)&j) //因为j才是剩下没用的木棍,不是i,所以是和j按位与 {//cout<<number[k]<<" " ;if(number[k]==number[i]){MAX=max(MAX,number[i]);}}}cout<<MAX;return 0;
}

别人写的java版(我也写了很多自己的注释进去)

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种排列组合方式  就是相当有n个元素有2^n个集合 length = new int[1<<n];//1<<n二进制的1向左移动n位得到的答案和2^n相等 开这么大的数组 for(int i=0;i<n;i++){nums[i] = scanner.nextInt();//存入几个木棍长度 //1<<i表示的下标  指的是只选第i根木棍的长度length[1<<i] = nums[i];//因为i是从0开始的 如果i从1开始 length[1<<(i-1)] = 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){//说明当前的j与组合方式没有选到同一个木棍,后面赋值就不准确 continue;//后面的语句不再执行 ,又执行 for语句中的j++ }//如果这种情况考虑在内了,那么第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;用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;//j是剩下的木棍 //接下来的循环是尝试从选择了全部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);}}

这篇关于无聊的逗(二进制法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

通信工程学习:什么是2ASK/BASK二进制振幅键控

2ASK/BASK:二进制振幅键控         2ASK/BASK二进制振幅键控是一种数字调制技术,其全称是二进制振幅键控(Binary Amplitude Shift Keying)。该技术通过改变载波的振幅来传递二进制数字信息,而载波的频率和相位则保持不变。以下是关于2ASK/BASK二进制振幅键控的详细解释: 一、2ASK/BASK二进制振幅键控的基本原理 1、振幅键控:

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1:输入:a = "11", b = "1"输出:"100"示例 2:输入:a = "1010", b = "1011"输出:"10101" 算法设计 可以从低位到高位(从后向前)计算,用一个变量carry记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对

Leetcode67---二进制求和

https://leetcode.cn/problems/add-binary/description/ 给出的两个二进制,我们可以从最后开始往前运算。 给当前短的一位前面补充0即可。 class Solution {public String addBinary(String a, String b) {//给的就是二进制字符串 最后一位开始遍历 如果没有就补充0?StringBuil

二进制的匹配问题

最近做了点搜索和背包的题目,发现这个二进制的匹配很是好用,所以写一篇二进制的匹配来作为自我总结; 首先我们要知道二进制的运算符,和他们的运算规则; ABA&BA|BA^B00000010111001111110 运算符有三种‘&’ , ‘|’ ,  ‘^'  或,且,异或,运算的规则在表中可以看到,想想这个规则我们可以做很多事情! 首先,每个十进制的数都会对应一个唯一的二进

二进制方式安装Helm

二进制方式安装Helm 官网:https://helm.sh/ 1、下载安装包 wget -L https://get.helm.sh/helm-v3.16.0-rc.1-linux-amd64.tar.gz 2、解压 tar -xf helm-v3.16.0-rc.1-linux-amd64.tar.gz 3、移动到/usr/local/bin/目录下 mv linux-am

输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。

/*** 输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。* 思路:第一步求这两个数的异或,第二步统计异或结果中1的位数*@author: Administrator*@date: 2017-1-13 下午09:39:25*/import java.util.Scanner;public class Solution4 {public int CountDifference

牛客网《剑指Offer》 二进制中1的个数

题目描述 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 思路 负数用补码,其实就是求一个数据在计算机中是存储是怎么样子的。用位运算,就能很好实现。 class Solution {public:int NumberOf1(int n) {int count = 0;int flag = 1;while (flag != 0) {if ((n & f

Java 二进制,八进制,十进制,十六进制之间的相互转换

package com.sjd.JinzhiZhuanhuan;public class JinzhiZhuanhuan {//二进制转八,十,十六进制---开始public void fromBinaryToOctalSting(String str1) {String result=Integer.toOctalString(Integer.parseInt(str1, 2));System.

JAX-WS - 二进制处理之MTOM(文件上传)

一、一般模式     服务端: import javax.jws.WebService;@WebServicepublic interface UploadService {public void upload(byte[] file);} import java.io.File;import java.io.FileOutputStream;import java.io.IOEx

信息学奥赛初赛天天练-83-NOIP2014普及组-基础题2-输入设备、输出设备、操作系统、二进制、整数除法、while、do while循环

1 NOIP 2014 普及组 基础题2 4 以下哪一种设备属于输出设备( ) A 扫描仪 B 键盘 C 鼠标 D 打印机 5 下列对操作系统功能的描述最为完整的是( ) A 负责外设与主机之间的信息交换 B 负责诊断机器的故障 C 控制和管理计算机系统的各种硬件和软件资源的使用 D 将没有程序编译成目标程序 11 下列各无符号十进制整数中,能用八位二进制表示的数中最大的是( ) A 296