UVa 183 - Bit Maps

题目

黑白图片存储有两种格式:位图格式和压缩格式;
位图格式:使用一个矩阵(元素为01)来表示一个黑白图片;
压缩格式:图像是单一颜色(全都是0或1),则图像为对应的值(0或1),否则图像的值为D,并将图形分成四个矩形(不能平均分时左侧和上侧多取一个像素),分别判断四个子图像,按照从上到下、从左到右的顺序组成一个字符串;
现在已知两种格式的某一种,需要转化到另一种;

分析

将两种转化分为两个过程,分别利用递归求解。
位图格式转化到压缩格式:先利用DP求解出每个矩形中的1的总和,然后利用面积可以快速判断,子图形是否只有一个颜色,然后递归计算四个子区域;
压缩格式转化到位图格式:如果是D利用递归求解,如果不是D则染色即可;

说明

注意数据格式,每行最多50个字符。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char Dmaps[40404];
int  Dmaps_count = 0;
int  line[202][202] = {0}, sum[202][202] = {0};
void B2D(int r1, int r2, int c1, int c2)
{
    int ones = sum[r2][c2] - sum[r1-1][c2] - sum[r2][c1-1] + sum[r1-1][c1-1];
    int area = (r2-r1+1)*(c2-c1+1);
    if (ones == 0 || ones == area) {
        Dmaps[Dmaps_count ++] = ones/area + '0';
        return;
    }
    if (r1 == r2 && c1 == c2) {
        Dmaps[Dmaps_count ++] = ones/area + '0';
        return;
    }
    Dmaps[Dmaps_count ++] = 'D';
    int mid_row = (r1 + r2)/2;
    int mid_col = (c1 + c2)/2;
    B2D(r1, mid_row, c1, mid_col); // block1
    if (mid_col < c2) {
        B2D(r1, mid_row, mid_col+1, c2); // block2
    }
    if (mid_row < r2) {
        B2D(mid_row+1, r2, c1, mid_col); // block3
        if (mid_col < c2) {
            B2D(mid_row+1, r2, mid_col+1, c2); // block4
        }
    }
}

char Bmaps[40404];
int  Dmaps_point = 0;
void D2B(int r1, int r2, int c1, int c2, int column)
{
    if ('D' != Dmaps[Dmaps_point]) {
        for (int i = r1; i <= r2; ++ i) {
            for (int j = c1; j <= c2; ++ j) {
                Bmaps[i*column + j] = Dmaps[Dmaps_point];
            }
        }
        Dmaps_point ++;
    }else {
        Dmaps_point ++;
        int mid_row = (r1 + r2)/2;
        int mid_col = (c1 + c2)/2;
        D2B(r1, mid_row, c1, mid_col, column); // block1
        if (mid_col < c2) {
            D2B(r1, mid_row, mid_col+1, c2, column); // block2
        }
        if (mid_row < r2) {
            D2B(mid_row+1, r2, c1, mid_col, column); // block3
            if (mid_col < c2) {
                D2B(mid_row+1, r2, mid_col+1, c2, column); // block4
            }
        }
    }
}

char buf[100], data[40404];
void image_input()
{
    data[0] = 0;
    while (1) {
        gets(buf);
        int blank = 0;
        for (int i = 1; buf[i]; ++ i) {
            if (' ' == buf[i]) {
                blank = i;
                break;
            }
        }
        int letter = 0;
        for (int i = blank; buf[i]; ++ i) {
            if (' ' != buf[i]) {
                letter = i;
                break;
            }
        }
        if ('#' == buf[0] || blank && letter) {
            return;
        }
        strcat(data+strlen(data), buf);
    }
}

int main()
{
    char type;
    int  row, column;
    gets(buf);
    while ('#' != buf[0]) {
        sscanf(buf, "%c %d %d", &type, &row, &column);
        image_input();
        if ('B' == type) {
            strcpy(Bmaps, data);
            for (int i = 1; i <= row; ++ i) {
                for (int j = 1; j <= column; ++ j) {
                    line[i][j] = line[i][j-1] + Bmaps[(i-1)*column + j-1] - '0';
                    sum[i][j] = sum[i-1][j] + line[i][j];
                }
            }

            Dmaps_count = 0;
            B2D(1, row, 1, column);
            printf("D%4d%4d\n%", row, column);
            for (int i = 0; i < Dmaps_count; ++ i) {
                if (i && i%50 == 0) {
                    printf("\n");
                }
                printf("%c", Dmaps[i]);
            }
            printf("\n");
        }else {
            strcpy(Dmaps, data);
            Dmaps_point = 0;
            D2B(0, row-1, 0, column-1, column);
            int Bmaps_count = row*column;
            printf("B%4d%4d\n%", row, column);
            for (int i = 0; i < Bmaps_count; ++ i) {
                if (i && i%50 == 0) {
                    printf("\n");
                }
                printf("%c", Bmaps[i]);
            }
            printf("\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值