poj1173 解題報告

2021-06-17 15:09:13 字數 1696 閱讀 1997

發現此題資料甚少,斗膽第一次寫乙份解題報告

【題意】

輸入 n(代表二進位制位數) k(代表黑條白條總共有幾條,條形碼是以黑條開始的,再白黑交替出現) m(代表每條最多佔多少個二進位制位)

輸出這種模式的條形碼的有多少個?

輸入s,再輸入s個二進位制形式的條形碼

輸出每個條形碼在該模式中的序號,序號是根據二進位制條形碼的十進位制數值排序,序號從0開始。

【解題思路】

動態規劃+組合數學。

我們舉乙個例子:n=7,k=4,m=3。

⑴計算個數

要計算此模式條形碼的數量,那麼我們只要分別計算出

n=6,k=3,m=3。

n=5,k=3,m=3。

n=4,k=3 ,m=3。

再講他們相加即可。

擴充套件到一般,得公式 [n,k] = ∑[n-i,k-1](i = 1,2···m-1,m)

根據推算,我們可以將公式化簡成  [n,k] = [n-1,k] + [n-1,k-1] - [n-m-1,k-1] 

我們令[0,0]=1,   令 [0,1]至[0,k]  和 [1,0]至[k,0] =0,其餘的值都可以通過遞推得到

⑵計算序號

首先將 長度為n的二進位制條形碼 轉換成 長度為k的向量,例如 1101110 -》 2131(2個1,1個0,3個1,1個0)

2131之前的條形碼可以分為四部分:

1???    [6,3] = 7

22??    [3,2] = 1

23??    [2,2] = 2

211?    [3,1] = 1

212?    [2,1] = 1

合計為12    對照下面題目給出的表 確是如此    

至於究竟上面是如何弄出來的,需要分黑條和白條分別考慮,不是很好說明,看**應該能懂。

還有一點,我們都知道0在二進位制位裡面越前,1越後,則該數值會越小(即序號越小)。

0: 1000100 | 8: 1100100

1: 1000110 | 9: 1100110

2: 1001000 | 10: 1101000

3: 1001100 | 11: 1101100

4: 1001110 | 12: 1101110

5: 1011000 | 13: 1110010

6: 1011100 | 14: 1110100

7: 1100010 | 15: 1110110

【**】

#include

using namespace std;

int n,k,m;

int dp[40][40]=;//下標分別對應著 n+1 和 k+1

int s;

char bin[40];//儲存每次輸入的二進位制串

int vec[40];//將二進位制的bin陣列 轉換成 k部分的向量

int count[102];

void table()//打表 計算還剩 n位 和 k部分時 有多少種情況

}void bintovec()//將二進位制的bin陣列 轉換成 k部分的向量 並且儲存到vec陣列中

vec[j++]=c;}}

int countorder()//計算該二進位制的序號

}else//針對編碼為0的部分

}u-=vec[i];

}return count;

}int main()

cout

poj1173 多重集組合數

這道題的本質是將n個物品分成k堆,每堆物品個數大於0小於等於m的方案數。我們定義d i j 為前i堆物品總數為j的方案數,那麼d i j 的求解方法如下 其可化為d i j d i j 1 d i 1 j 1 d i 1 j 1 m 初始條件為d 0 0 1 d i 0 0 i 0 證明如下 對於第...

poj解題報告 1328

不得不說,這題是讓我飽受折磨,畢竟第一次做貪心演算法,而且wa了好多次,幸好有學長的幫助,最終找到了問題所在,是在快排上是問題,double高位不可向int低位轉換,由於一開始強制轉換導致雖然樣例和其他的測試資料過了,但還是wa,現在改完了就對了,附上ac ps 這題通過率是22 真心不簡單 如下 ...

poj解題報告 2586

這題我是用的貪心演算法,其實不用也可以,列舉也能解決,因為情況不多。因為是每連續5個月必有虧損,而一年只有1 5,2 6,3 7,4 8 8 12共8種情況。現在設盈餘為s,虧損為d,可列出以下幾種情況。ssssdssssdss 4ssssddsssddss 3s 2d ssdddssdddss 2...