尤拉計劃287題:四分樹編碼(一個簡單的壓縮演算法)
四分樹編碼使我們能夠將一個2N×2N的黑白圖片表示為一個位元串(0和1)。該位元串可以從左到右解讀為:
◦第一個位元位描述完整的2N×2N區域;
◦“0”表示對當前區域進行分割:
將當前的2n×2n區域分割為4個2n-1×2n-1區域,
接下來的位元位按照左上、右上、左下、右下的順序分別描述這四個區域;
◦“10”表示當前區域只包含黑色畫素;
◦“11”表示當前區域只包含白色畫素。
考慮如下的4×4圖象(彩色標記意味著需要進行分割的位置):
這個影像可以用多個不同的位元串表示,例如:
“001010101001011111011010101010”,長度為30,或者
“0100101111101110”,長度為16,後者是描述這幅圖象的最短位元串。
對於一個正整數N,記DN是按照如下染色方案得到的2N×2N圖象:
◦左下角的畫素其座標為x = 0,y = 0,
◦如果(x - 2N-1)2 + (y - 2N-1)2 ≤ 22N-2,那麼該座標的畫素為黑色,
◦否則該座標的畫素為白色。
描述D24的最短位元串長度是多少?
用julia來模擬一下
N=2 #b=Array{Array}(N); #b[i]=zeros(Int,N) b=[zeros(Int,2^N) for i in 1:2^N] function setcolor_D(N) N1=N-1 for x in 0:2^N-1 for y in 0:2^N-1 if (x-2^N1)^2+(y-2^N1)^2≤2^2N1 b[x+1][y+1]=1 end end end end b
輸出
4-element Array{Array{Int32,1},1}: [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] 4-element Array{Array{Int32,1},1}: [0, 0, 1, 0] [0, 1, 1, 1] [1, 1, 1, 1] [0, 1, 1, 1] #N=3 julia> b 8-element Array{Array{Int32,1},1}: [0, 0, 0, 0, 1, 0, 0, 0] [0, 0, 1, 1, 1, 1, 1, 0] [0, 1, 1, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1, 1, 1] [0, 0, 1, 1, 1, 1, 1, 0]
從公式和圖形看,黑色部分是以(2n-1,2n-1)為圓心,2n-1為半徑的圓盤和矩陣的重合部分。
上述陣列的陣列其實並非適合這道題的資料結構,更好的辦法是用二維陣列,如下程式碼畫出示例的矩陣(上下倒置)。
c=ones(Int,4,4); c[1,1]=0; c[2,1]=0; c[1,2]=0; c[2,2]=0; c[3,3]=0; c[4,4]=0; #結果 julia> c 4××4 Array{Int32,2}: 0 0 1 1 0 0 1 1 1 1 0 1 1 1 1 0
然後編寫如下的程式碼
function D(b,N) N1=N-1 for x in 0:2^N-1 for y in 0:2^N-1 if (x-2^N1)^2+(y-2^N1)^2<=2^2N1 b[x+1,y+1]=1 end end end return b end function code(a,len) if a==ones(Int,len,len) return "10" end if a==zeros(Int,len,len) return "11" end half=div(len,2) s="0"; s=s * code(view(a,1:half,1:half),half) s=s * code(view(a,1:half,half+1:half*2),half) s=s * code(view(a,half+1:half*2,1:half),half) s=s * code(view(a,half+1:half*2,half+1:half*2),half) return s end N=2 c=zeros(Int,2^N,2^N) D(c,N) code(c,2^N) function p287(N) c=zeros(Int,2^N,2^N) D(c,N) return length(code(c,2^N)) end
code函式針對示例的輸出
julia> code(c,4) "0111010011101011" julia> length(code(c,4)) 16 #對於題目要求的生成矩陣 julia> p287(2) 30 julia> map(x->(x,p287(x)),1:10) 10-element Array{Tuple{Int32,Int32},1}: (1,9) (2,30) (3,86) (4,212) (5,499) (6,1052) (7,2242) (8,4552) (9,9382) (10,18790)
但更大的N,記憶體溢位了,需要用另外的方法。
將大矩陣分解成小矩陣,2*2的四方格,如果不全同色需要9位(=1*0佔的1位+4*每個1*1單元格的2位),如果同色,需要2位,更大的2n*2n矩陣,純色只要2位,不純色的同上處理。下圖顯示了n=2~4的分解。
分別用2個陣列儲存0和不同尺寸的矩陣個數。當N=5時,資料如下:
julia> f0 2-element Array{Int32,1}: 71 0 julia> [(i,f[i]) for i in 1:2^N if f[i]>0] 4-element Array{Tuple{Int32,Int32},1}: (1, 124) (2, 61) (4, 25) (8, 4)
把5~11的結果做成一個表格,得出以下規律,最大的矩陣個數等於4,最小的是2n+2-4,0的個數等於(子矩陣個數之和-1)/3。
相關文章
- 簡單的zip壓縮和解壓縮
- CSP之壓縮編碼(動態規劃)動態規劃
- 000. 尤拉計劃簡介
- 一個簡單的統計問題(解決方案:Trie樹)
- 【Node】簡單快捷的圖片壓縮指令碼指令碼
- 尤拉計劃512題(冪的尤拉總計函式和)函式
- 尤拉計劃433題:歐幾里德演算法的步數演算法
- 計算機演算法:資料壓縮之字首編碼(5)計算機演算法
- 計算機演算法:資料壓縮之遊程編碼計算機演算法
- 貪心演算法——Huffman 壓縮編碼的實現演算法
- 超級簡單的資料壓縮演算法—LZW演算法演算法
- 簡單好用的js 壓縮工具JS
- 計算機演算法:資料壓縮之相對編碼(4)計算機演算法
- 一個強大的圖片壓縮演算法—近微信壓縮機制的Luban演算法
- 一個簡單的樹查詢
- 【leetcode 簡單】 第一百零六題 壓縮字串LeetCode字串
- javascript編寫一個簡單的編譯器(理解抽象語法樹AST)JavaScript編譯抽象語法樹AST
- 對尤拉計劃427題(n-序列) 的一些分析
- Word檔案太大怎麼壓縮,分享壓縮Word的簡單方法
- 怎麼把影片壓縮?實用又簡單的壓縮影片方法
- 尤拉計劃595題:增量隨機排序隨機排序
- 尤拉計劃425題:質數連線
- 壓縮演算法一覽演算法
- 尤拉計劃463題:奇怪的遞迴關係遞迴
- 一個簡單的樹形結構
- 批次壓縮影片大小的簡單操作分享
- 圖片壓縮知識梳理(0) 圖片壓縮學習計劃
- 高效的資料壓縮編碼方式 Protobuf
- 影像壓縮編碼碼matlab實現——行程編碼Matlab行程
- 影像壓縮編碼碼matlab實現——DM編碼Matlab
- 雙指標演算法的一個簡單題解指標演算法
- 尤拉計劃605題:結對投幣遊戲遊戲
- 計算機演算法:資料壓縮之圖編碼和模式替換(3)計算機演算法模式
- Hive的壓縮儲存和簡單優化Hive優化
- Python編寫一個簡單計算器Python
- 一個網友求助的軟體的演算法分析------explzh好象是壓縮與解壓縮軟體演算法
- javascript編寫一個簡單的編譯器JavaScript編譯
- 影像壓縮編碼碼matlab實現——變換編碼Matlab