小H和密码

链接:https://www.nowcoder.com/acm/contest/72/B
来源:牛客网

题目描述

    小H在击败怪兽后,被一个密码锁挡住了去路
    密码锁由N个转盘组成,编号为1~N,每个转盘有M个位置,每个位置上要么有一个小写字母,要么没有任何字符。一个密码能被转盘表示出,当且仅当指定每个转盘上面的某一个位置,然后将这些位置按照所属的转盘编号顺次连接(空位置直接忽略),可以得到这个密码
    小H并没有得到任何线索,因此只能猜,她一共猜了Q次,但并不知道自己猜的密码能否被表示出来,于是她向你求助

输入描述:

第1行,三个整数N,M,Q
第2~N+1行,每行一个长度为M的字符串,依次表示每个转盘上的字符
第N+2~N+Q+1行,每行一个长度不超过10000的字符串,表示小H猜的密码
2≤N,Q≤300,2≤M≤27,同一个转盘上每种字符最多出现一次

输出描述:

输出Q行,每行都是YES或NO,依次表示小H猜的每个字符串能否被表示出
示例1

输入

3 2 3 
a# 
ab 
bc 
aa 
bb 
ba

输出

NO
YES
NO

备注:

#表示空字符

分析:

用贪心确定每个密码盘选哪个字符是错误的

递归肯定超时,剪枝都补救不了

所以这题看起来字符串模拟的题,居然要用dp写。。。

考虑DP,设dp[i][j]表示前i个密码盘,有j个选了某个小写字母的方案     时间复杂度O(N^2Q)

则决策只有当前密码盘选择空字符或者小写字母两种

用桶记录每个位置有哪些可用字母,询问串过长直接输出NO

重点:初始化+bool传递

 

 所以第二位选0个的项都设为1

看别人代码,学了一招,传递可行性用&1,很骚


#include<bits/stdc++.h>
using namespace std;
#define maxn 10000
typedef long long ll;
#define inf 2147483647
#define ri register int

int n,m,q;
int str[400][30];
int dp[400][400];
char ss[maxn],s[maxn];

int main()
{
//    freopen("test.txt","r",stdin);
//  freopen("outout.txt","w",stdout);
    cin>>n>>m>>q;
    for(int i=1; i<=n; i++)
    {
        scanf("%s",ss);
        for(int j=0; j<strlen(ss); j++)
        {
            if(ss[j]=='#')
                str[i][0]=1;
            else str[i][ss[j]-'a'+1]=1;
        }
    }
    while(q--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%s",s+1);
        int len=strlen(s+1);
        if(len>n){
            cout<<"NO"<<endl;
            continue;
        }
        for(int i=0; i<=n; i++)
            dp[i][0]=1;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=i; j++)
            {
                if(str[i][s[j]-'a'+1])
                    dp[i][j]=dp[i-1][j-1]&1;
                if(str[i][0]&&!dp[i][j])
                    dp[i][j]=dp[i-1][j]&1;
            }
        if(dp[n][len])
            cout<<"YES";
        else cout<<"NO";
        cout<<endl;
    }
    return 0;
}

posted @ 2018-02-25 11:16  planche  阅读(187)  评论(0编辑  收藏  举报