0
点赞
收藏
分享

微信扫一扫

蓝桥杯 试题 算法训练 Bit Compressor (dfs+剪枝)


问题描述

  数据压缩的目的是为了减少存储和交换数据时出现的冗余。这增加了有效数据的比重并提高了传输速率。有一种压缩二进制串的方法是这样的:
  将连续的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

解题思路:

在蓝桥杯网站上,这道题的归类为dp,但是这道题却不能用dp。dp即动态规划,使用条件需要问题是求最优解的,所以不能用dp求这道题。

用dfs求解:一点点的增加二进制串的长度,直到长度为指定的长度,并且1的 个数 也为指定的长度。

剪枝:根据(译者注:连续的n个1的左右必须是0或者是串的开头、结尾)这句话来剪枝。

string的使用技巧:参考我之前总结的stl的博客

#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int l,n,ans;
int f(string s){//二进制转换成十进制
int num=0;
string ss(s.rbegin(),s.rend());
for(int i=0;i<ss.length();i++)
num+=(ss[i]-'0')*pow(2,i);
return num;
}
int num_n(string s){//计算串中1的个数
int num=0;
for(int i=0;i<s.length();i++)
if(s[i]=='1') num++;
return num;
}
void dfs(string s,int begin){
if(ans==2) return;
if(s.length()==l&&num_n(s)==n)
{
ans++;
return;
}
int s_len=s.length();
for(int i=begin;i<s_len;i++)
{
if(s[i]=='0') continue;
if(i>0&&s[i-1]=='1') continue;//除了开头,前面必须是0
for(int j=2;i+j<=s_len;j++)//j表示str的长度,也就是选择解压的长度
{
if((i+j)<s_len&&s[i+j]=='1') continue;//除了末尾,后面也必须是0
string str(s,i,j);//提取待解压的子串str
int len=f(str);//str解压缩后的长度
int str_len=str.length();//str解压缩前的长度
if(str_len==len) continue;//解压缩不能使得字符串变长
if((s_len-str_len+len)>l) break;//解压后的总长度大于l
string s1="";
if(i!=0)//如果不是开头
{
string ss(s,0,i);//提取之前的子串
s1+=ss;
}
for(int k=0;k<len;k++)
s1+="1";
if((i+j)!=s_len) //如果不是末尾
{
string ss(s,i+j);//提取之后的子串
s1+=ss;
}
dfs(s1,i+len);
if(ans==2) return;
}
}
}
int main()
{
while(cin>>l>>n)
{
ans=0;
string s;
cin>>s;
dfs(s,0);
if(ans==0) cout<<"NO"<<endl;
else if(ans==1) cout<<"YES"<<endl;
else cout<<"NOT UNIQUE"<<endl;
}
return 0;
}

 

举报

相关推荐

0 条评论