發現此題資料甚少,斗膽第一次寫乙份解題報告
【題意】
輸入 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...