算法训练 Bit Compressor (dfs 剪枝)

试题 算法训练 Bit Compressor

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  数据压缩的目的是为了减少存储和交换数据时出现的冗余。这增加了有效数据的比重并提高了传输速率。有一种压缩二进制串的方法是这样的:
  加粗样式将连续的n个1替换为n的二进制表示(注:替换发生当且仅当这种替换减少了二进制串的总长度)
  (译者注:连续的n个1的左右必须是0或者是串的开头、结尾)
  比如:11111111001001111111111111110011会被压缩成10000010011110011。原串长为32,被压缩后串长为17.
  这种方法的弊端在于,有时候解压缩算法会得到不止一个可能的原串,使得我们无法确定原串究竟是什么。请你写一个程序来判定我们能否利用压缩后的信息来确定原串。给出原串长L,原串中1的个数N,以及压缩后的串。
  L<=16 Kbytes,压缩后的串长度<=40 bits。
输入格式
  第一行两个整数L,N,含义同问题描述
  第二行一个二进制串,表示压缩后的串
输出格式
  输出"YES"或"NO"或"NOT UNIQUE"(不包含引号)
  分别表示:
  YES:原串唯一
  NO:原串不存在
  NOT UNIQUE:原串存在但不唯一
样例输入
样例1:
32 26
10000010011110011
样例2:
9 7
1010101
样例3:
14 14
111111
样例输出
样例1:YES
样例2:NOT UNIQUE
样例3:NO

AC代码如下:
代码来自https://blog.csdn.net/yi_qing_z/article/details/88084875,稍有改动

#include<stdio.h>
#include<cstring>
#define maxn 50
int L,l,N;
char data[maxn];
int answer;
 
void dfs(int i,int length,int num_1) {
		//i是原串第i个字符,length是变换后的串长,num_1是变换后串的1累计个数 
    if(i==l){		//最后一个位置 
        dfs(i+1,length+1,num_1+data[i]-'0');
        return;		//最后一个位置是0的话data[i]-'0' =0  是1的话data[i]-'0'=1
    }
    if(i>l)	{	//结束条件 
        if(length==L&&num_1==N)	//字符串的长度和1的个数正好匹配
            answer++;
        return;
    }
    
    if(length>L||num_1>N||answer>=2)	//不符合条件,提前返回 
        return;
        
    if(data[i]=='0'){	//如果这一位为0,那么不用考虑情况
        dfs(i+1,length+1,num_1);
        return;
    }
    
    // 以下为 data[i]=='1' 的情况
    if(data[i-1]=='1')		
    	//即...11... 在处理上一个1或者更久之前已经考虑过了,注意看下面6行的代码 
        return;
        
        //以下是data[i-1]=='0'的情况
    if(data[i+1]=='0')	
    	//即 ...010... 的情况,这种情况考虑的是1不压缩的情况
        dfs(i+1,length+1,num_1+1);
    if(data[i+1]=='1'&&data[i+2]!='1')	
    	//即 ...0110... 这种考虑的是不压缩的情况
        dfs(i+2,length+2,num_1+2);
 //注意,以上两种情况1均有可能代表压缩的情况,比如...0110.. 原串为...011110...压缩了3个1
 //下面的代码对每一个1均考虑其为压缩  
    long long temp=0;
    for(int j=i;j<=l;j++){
        temp*=2;
        temp+=data[j]-'0';	
        	//上面两行代码实现二进制转十进制,就是解压缩后1的个数
        if(temp+num_1>N||temp+length>L)	
       		 //如果解压缩的编码长度或者1的个数比原来的大,不可行,返回
            break;
        if(temp>j-i+1&&data[j+1]!='1')		
     	  //压缩的串1比原来多,并且下一个位置为0或者末尾,就是可行解,继续深搜
            dfs(j+1,temp+length,num_1+temp);
    }
}
 
 
int main()
{
    scanf("%d",&L);		//原串长
    scanf("%d",&N);		//原来1的个数 
    scanf("%s",data+1);
    l=strlen(data+1);		//新串长 
    answer=0;
    dfs(1,0,0);
    if(answer==0)
        printf("NO");
    else if(answer==1)
        printf("YES");
    else
        printf("NOT UNIQUE");
    return 0;
}
Compressor是一种基于LZ77算法的压缩算法,其垃圾回收算法主要是为了解决压缩过程中会产生的垃圾数据占用过多内存的问题。 Compressor的垃圾回收算法主要有两种:标记-清除算法和复制算法。 1. 标记-清除算法 标记-清除算法是一种常见的垃圾回收算法。在Compressor中,当需要压缩新的数据时,会在内存中分配一块新的区域来存储压缩后的数据。在这个过程中,会产生一些无用的数据,这些数据会被标记为垃圾数据。当内存中垃圾数据的总量达到一定的阈值时,就会触发垃圾回收算法。具体步骤如下: (1)从压缩区域开始,遍历整个内存空间,标记所有被引用的数据。 (2)遍历整个内存空间,清除所有未被标记的数据。 (3)将所有被标记的数据向内存空间的一端移动,使得它们在一段连续的区域内,以便后续的压缩操作。 2. 复制算法 复制算法是一种常见的垃圾回收算法,在Compressor中也得到了应用。该算法将内存空间分成两个区域,一块是压缩区域,另一块是临时区域。在压缩数据时,会将压缩后的数据存储在临时区域中,然后将压缩区域中的所有数据移动到临时区域的另一端,以便后续的压缩操作。具体步骤如下: (1)将所有已经压缩过的数据从压缩区域复制到临时区域中。 (2)将压缩区域中的所有数据向内存空间的一端移动,以便后续的压缩操作。 (3)将临时区域中的数据复制回压缩区域中,并清除临时区域。 Compressor的垃圾回收算法可以根据具体情况进行选择,以达到更好的压缩效果和更高的压缩速度。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值