1. 程式人生 > 其它 >洛谷P2556 [AHOI2002]黑白影象壓縮

洛谷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個十進位制形式的位元組量,表示該影象的點陣圖資訊。相鄰數之間用一個空白字元隔開。

輸出格式

以一行的形式輸出以畫素片段表示法表示的影象資訊,各個數都以十進位制的形式出現,相鄰數之間用一個空白字元隔開。

輸入輸出樣例

輸入 #1
8 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;
}

(參考洛谷題解)