洛谷P2556 [AHOI2002]黑白影象壓縮
題目描述
選修基礎生物基因學的時候, 小可可在家裡做了一次影象學試驗。 她知道:整個影象其實就是若干個影象點(稱作畫素)的序列,假定序列中畫素的個數總是 8 的倍數, 於是每八個畫素可以轉換成一個叫做位元組的數, 從而這個表示影象的畫素序列就被轉換成了位元組的序列。
所謂的位元組就是一個八位的二進位制數(當然,為了便於書寫,人們經常用它的十進位制形式來表示)。這八個畫素從前向後依次對應於位元組從高位到低位的八個位, 用 0 來表示白色畫素、 1 來表示黑色畫素。 這種表示方法叫做點陣圖法。 例如位元組序列 210、 0、255 表示了 8*3=24 個畫素, 由於對應的二進位制形式是 11010010、 00000000、11111111, 所以這 24 個畫素的顏色依次是黑、 黑、 白、 黑、 白、 白、 黑、 白、白、白、白、白、白、白、白、白、黑、黑、黑、黑、黑、黑、黑、黑。
小可可想: 其實影象中存在著很多連續的同色畫素段, 也許換一種方式表達影象能夠減少影象的資料量。 她的思路是: 把畫素按照顏色分成若干個片段, 同一個片段中各畫素顏色相同, 且連續的同色畫素都在同一個片段中。同時已知每個片段的最大長度小於 128。
每一個畫素片段都是用一個二進位制位元組量來表示, 最高位表示片段中畫素的顏色, 而低七位表示片段中畫素的數目。注意:不存在長度為 0 的畫素片段。這種表示法叫做畫素片段法。
例如位圖表示法的位元組序列 210、 0、 255 對應的畫素序列可以分成七個片段,分別是: 11、 0、 1、 00、 1、 000000000、 11111111。如果用畫素片段法來表示的話,二進位制位元組序列應該寫成 10000010、 00000001、 10000001、00000010、 10000001、 00001001、 10001000, 而其對應於十進位制位元組序列就是 130、 1、 129、 2、 129、 9、 136。
畫素片段法是否能有效地減少影象的資料儲存量呢?小可可不知道如何用數學的方法加以證明, 於是決心對手頭上的影象做些試驗, 看看該方法是否真的有效。 請你編寫程式完成影象資訊的轉換, 以協助小可可完成這項試驗。
輸入格式
檔案中以一行的形式存放了一個影象的資訊。第一個數是正整數 n ,表明該影象有 n 個畫素。隨後有 n/8個十進位制形式的位元組量,表示該影象的點陣圖資訊。相鄰數之間用一個空白字元隔開。
輸出格式
以一行的形式輸出以畫素片段表示法表示的影象資訊,各個數都以十進位制的形式出現,相鄰數之間用一個空白字元隔開。
輸入輸出樣例
輸入 #18 0輸出 #1
8輸入 #2
24 210 0 255輸出 #2
130 1 129 2 129 9 136
說明/提示
1≤n≤8×104
題目解析:
首先,把輸入的所有數字a由十進位制轉換為二進位制,逆序存放在一個數組b裡。
隨後,判斷陣列b中相鄰的數字是否相同,相同就繼續,若不相同,則根據畫素來計算其對應的十進位制數,若畫素是1,則需要在最後的結果s上加上128,若畫素是0,則不用加。
最後,將得出的數字輸出。
總結: 做這個題目時,沒能考慮到一個數全為 0 ,或者一個數二進位制的最後一位為 1 ,而下一個數的二進位制第一位為 0 的情況。
程式碼:
#include <iostream> #include <cstdio> using namespace std; int a[80000],b[80000]; int main() { int n,k=0,s=1; cin>>n; int m=n/8,i,j; for (i=0;i<m;i++) cin>>a[i]; for (i=0;i<m;i++) for (int j=7;j>=0;j--) { k=i*8+j; b[k]=a[i]%2; a[i]/=2; } for (i=1;i<n;i++) if (b[i]!=b[i-1]) { if (b[i-1]==1) cout<<s+128<<" "; else cout<<s<<" "; s=1; } else s++; if (b[i-1]==1) cout<<s+128<<endl; else cout<<s<<endl; return 0; }
(參考洛谷題解)