HNUST 1520: 压缩编码

1520: 压缩编码

时间限制: 1 Sec   内存限制: 2 MB
提交: 104   解决: 51
[ 提交][ 状态][ 讨论版]

题目描述

  某工业监控设备不断发回采样数据。每个数据是一个整数(0到1000之间)。各个数据间用空白字符(空格,TAB或回车换行)分隔。
   因为大多数时候,相邻的采样间隔数据是相同的,可以利用这个特征做数据的压缩存储。其方法是:对n(n>1)个连续相同的数字只记录n和该数字本身;对m(m>0)个连续不重复的数字,则记录 m*-1 和这些数字本身(之所以用负数,是为了与第一种情况区分,便于解压缩)。
 
    例1:
    假设采样数据为:
    12 34 34 25 25 25 25 11 15 17 28 14 22 22 22  
    则将上述采样数据按照上述规则进行压缩编码后的数据为:
    -1 12 2 34 4 25 -5 11 15 17 28 14 3 22
    例2:
    假设采样数据为:
    12 13 14 13 12
    则将上述采样数据按照上述规则进行压缩编码后的数据为:
    -5 12 13 14 13 12
    例3:
    假设采样数据为:
    66 66 66 66 66 88 88 88 88 88 88 88 88 88 88 88 
    则将上述采样数据按照上述规则进行压缩编码后的数据为:
    5 66 11 88

输入

先输入采样数据的个数n(1<=n<=10000)。

然后输入n个采样数据。每个数据是一个整数(0到1000之间,包括0和1000本身)。各个数据间用空白字符(空格,TAB或回车换行)分隔。

输出

输出按规则进行压缩编码后的数据,数据之间用一个空格隔开。

注意,最后一个输出数据之后,没有空格,而是换行符。


见代码。
/**此题真的是坎坷,写个报告纪念一下**/
/**基本思路就是首先转化,将相同的数字在倒数第二位留下个数,最后一位取负,
例如12 34 34 25 25 25 25 11 15 17 28 14 22 22 22 13变为12  -2000  -34  -2000
  -2000  -2000  -25  11  15  17  28  14  -2000  -2000  -22  13-2000是一个
  标记数B,见下。(因为题目数据范围是0到1000,刚开始我没注意,标记的是0,
吃了一波亏)。然后就是一个转化算法,具体看代码注释咯**/
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int a[10005];
const int B=-2000;
const int C=-3000;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    for(int i=0; i<n; i++)
    {
        if(a[i]==a[i+1])  ///相同的数前面的位数标为B
            a[i]=B;
    }
    for(int i=0; i<n-1; i++)
    {
        if(a[i]==B&&a[i+1]!=B)///相同数的最后一个标为负数
            a[i+1]*=-1;
    }
    for(int i=1; i<n; i++)
    {
        if(a[i]==0&&a[i-1]==B)  /**重点来了,因为数据包含零,0取负还是0没有变化,于是特判标记为C**/
            a[i]=C;            ///这一段代码我没有简化。其实大家可以试试看,不难的。
    }
  /* for(int i=0; i<n; i++)///检测函数,自己看的
     printf("%d  ",a[i]);
   printf("\n");*/
    int sum_fei=0,sum_t=0;   ///sum_fei是不同数的总数,sum_t是相同数的总数减一
    int first=0;             ///因为每两个数之间要输出空格,这个是标记是否为首位输出的
    for(int i=0; i<n; i++)
    {
        if(a[i]>=0)         ///不同数。++
            sum_fei++;
        else if(a[i]==B)    ///因为转化后,每一个B前面势必是不同数的输出(如果前一位不是B),这儿是判断
        {
            if(i>=1)  ///因为保证 i-1 要大于等于0,就加了句废话
            {
                if(a[i-1]>=0)
                {
                    if(!first)
                    {
                        printf("%d",-1*sum_fei);
                        first=1;
                    }
                    else
                        printf(" %d",-1*sum_fei);

                    for(int j=i-sum_fei; j<i; j++)
                        printf(" %d",a[j]);
                    sum_fei=0;    ///输出后总数记0,以便下次使用
                }
            }
            sum_t++;
        }
        else
        {
            if(!first)
            {
                printf("%d",sum_t+1);   ///相同数的输出部分
                first=1;
            }
            else
                printf(" %d",sum_t+1);
            if(a[i]==C)                ///对于0的特判
                printf(" 0");
            else
                printf(" %d",-1*a[i]);
            sum_t=0;
        }
        if(i==n-1&&sum_fei!=0)   ///这是最后一个细节,就是输出到尾部的时候,最后一
        {                        ///组数可能不会输出。这里特别处理一下。
            if(!first)
                printf("%d",-1*sum_fei);
            else
                printf(" %d",-1*sum_fei);
            for(int j=n-sum_fei; j<=i; j++)
                printf(" %d",a[j]);
            sum_fei=0;
        }
    }
    printf("\n");///总体感觉这个代码废话太多,算法不优化。我继续加油,大家先凑合着吧
    return 0;    ///谢谢观看哈!!!
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值