【2018寒假集训Day 1】【位运算】生成字符串

 

生成字符串(strs)
【问题描述】
假设字符串只由字符“0”,“1”,“”组成,其中字符“”表示该字符可由
字符“0”或“1”替代。
现有一些字符串,根据这些字符串生成所有可生成的字符串。如:
{10,1,0 }可生成{10,01,11,00 }
{101,001,*01}可生成{101,001}
注意后一个例子中“*01”并没有生成新的字符串。
【输入格式】strs.in
第一行是两个整数 m,n(1≤m≤15,1≤n≤2500)。m 表示字符串的长度,n
表示字符串的个数。
以下 n 行每行各有一个字符串。文件中各行的行首、行末没有多余的空格。
【输出格式】strs.out
一个整数,表示所能生成的字符串的个数。
【输入样例】
2 3
10
*1
0*
【输出样例】
4
【解题思路】
显而易见,这题就是枚举+去重,枚举很简单,DFS可以轻松解决,但是判重是本题的重点,生成字符串后再往前一个一个比对是否出现过很浪费时间。
所以,可以利用把字符串压缩成一个整数,这些字符串都是01串,我们可以将其转换成数字后转换为十进制整数,再用数组计数,可以大幅度缩小需要的空间。
【参考程序】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m,count[16],a[70000],sum,n;
string st;
int change(string num)
{
    int ans=0;
    for (int i=0;i<m;i++)
    if (num[i]=='1') ans+=count[i];
    return ans;
}
void dfs(string st,int p)
{
    if (p>=m) 
    {
        int tmp=change(st);//转换进制 
        a[tmp]++;//数组计数 
        return ;
    }
    if (st[p]!='*') 
    {
        dfs(st,p+1);
        return ;    
    }//不是星号,直接往下一层。 
    st[p]='1';//用1代替星号 
    dfs(st,p+1);
    st[p]='0';//用0代替星号 
    dfs(st,p+1);
}
int main()
{
    freopen("strs.in","r",stdin);
    freopen("strs.out","w",stdout);
    cin>>m>>n;
    count[0]=1;
    for (int i=1;i<m;i++) count[i]=count[i-1]<<1;//为二进制转换做准备 
    for (int i=1;i<=n;i++)
    {
        cin>>st;
        dfs(st,0);
    }
    for (int i=0;i<count[m-1]*2;i++) if (a[i]>0) sum++;//统计 
    cout<<sum;
    return 0;
}
posted @ 2018-02-01 21:25  Nanjo  阅读(287)  评论(0编辑  收藏  举报