日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

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

發(fā)布時(shí)間:2025/3/20 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ-4004:数字组合(用位移方法解组合数问题,Java版) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述:

? ? 看完題目大家應(yīng)該就會(huì)想到這題可以用一個(gè)組合數(shù)的思路去編寫代碼。也就是說我們從給出的一個(gè)數(shù)組中去隨機(jī)地抽取中若干個(gè)數(shù)相加,相加的和要等于給出的那個(gè)數(shù)。雖然大致思想是沒錯(cuò)了,但是,具體的思路是怎么樣的呢?


思路分析:

? ? 我們是不是會(huì)有一種通用的方法來得到一維數(shù)組,用來告訴計(jì)算機(jī),這個(gè)一維數(shù)組的某一個(gè)位置是我要選取的數(shù)呢?

可能大家都會(huì)想到的是遞歸,不過我一個(gè)朋友給了我另一個(gè)思路,那就是用位移來解決這個(gè)問題。為什么用位移,因?yàn)榭?#xff01;

? ? 這里面有一個(gè)小技巧,那就是1<<n是等于2的n次方(例如1<<5 = 32)。也就是說把1左移n位,這里會(huì)得到一個(gè)結(jié)果,這個(gè)結(jié)果就是我們這個(gè)一維數(shù)組全部的子集,也就是全部的組合數(shù)。

? ? 其實(shí)如果你了解數(shù)字在計(jì)算機(jī)中的存儲(chǔ)和遞增過程,那么你就會(huì)得到一個(gè)有趣的結(jié)論,那就是我從0(空集)到1<<n這些數(shù)代表的就是我們要告訴計(jì)算機(jī)在那些位上是我們需要留下的,那些位上的數(shù)是我們不需要的。關(guān)于數(shù)字在計(jì)算機(jī)中的存儲(chǔ)和遞增過程這里不作講解。有興趣的朋友可以去查閱相關(guān)資料。

? ? 以上只是得到了全部的組合數(shù)。而他們也都是單個(gè)數(shù)字代表的,那我們能不能通過某種操作或是計(jì)算來獲得一個(gè)標(biāo)志數(shù)組或是某他的什么東西來說明,當(dāng)前數(shù)組的第i位是需要的呢?因?yàn)閱问且粋€(gè)數(shù)字代表的某種組合還不能讓計(jì)算機(jī)完全理解,我們需要的是哪個(gè)位置的值。

下面我們假設(shè)有一個(gè)數(shù)字5,那我們應(yīng)該怎么得到這個(gè)數(shù)字5所代表的組合呢?

0101
0001
上面的表格的第一行是數(shù)字5,第二行是數(shù)字1.

我們現(xiàn)在假設(shè)題目中告訴我們的是只有4個(gè)數(shù)。

那么,我們先得到a&1的值(&是位且操作符,它的作用是當(dāng)兩個(gè)數(shù)的每個(gè)二進(jìn)制位的值都是1時(shí),該位的值才是1,。。。。。。。想知道具體的,請(qǐng)查閱資料)。

這樣,我們由第一個(gè)表格就可以得到一個(gè)數(shù)字1,我們把它保存在b[0]中。

這時(shí),a右移a>>1 = 0010b

0010
0001
同理,這時(shí)b[1] = 0

a右移a>>1 = 0001

0001
0001
b[2] = 1

a右移a>>1 = 0000

0000
0001
b[3] = 0

a的位移結(jié)束。。。這時(shí)我們就得到了一個(gè)一維數(shù)組b[] = {1, 0, 1, 0};

我們可以看到它就是我們的a的二進(jìn)制的逆序,如果你不喜歡逆序,那就用自己的方式獲得正序的數(shù)組。


關(guān)于a的位移關(guān)鍵代碼:

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;/*** 通過位移得到一個(gè)組合數(shù)的一維數(shù)組* @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;}/*** 得到某個(gè)bit數(shù)組所對(duì)應(yīng)的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;}/*** 得到整個(gè)數(shù)組中共有多少個(gè)這樣的組合數(shù)* @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));} }


這里再給出我另一篇博客,《用遞歸和位移進(jìn)行枚舉子集合》這里是介紹了用遞歸和位移兩種方法進(jìn)行枚舉子集合的過程,感興趣的朋友可以去看看。。。

點(diǎn)擊連接進(jìn)行查看。

總結(jié)

以上是生活随笔為你收集整理的POJ-4004:数字组合(用位移方法解组合数问题,Java版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。