• 洛谷 P2167 [SDOI2009]Bill的挑战


    题目描述

    输入输出格式

    输入格式:

    本题包含多组数据。 第一行:一个整数T,表示数据的个数。 对于每组数据: 第一行:两个整数,N和K(含义如题目表述)。 接下来N行:每行一个字符串。

    输出格式:

    1 2 1 a? ?b

    输入输出样例

    输入样例#1:
    50
    输出样例#1:
    对于30%的数据,T ≤ 5,M ≤ 5,字符串长度≤ 20;
    
    对于70%的数据,T ≤ 5,M ≤ 13,字符串长度≤ 30;
    
    对于100%的数据,T ≤ 5,M ≤ 15,字符串长度≤ 50。

    真是玄学题
    经历了从50分到70分再到AC
    一开始看到觉得是带通配符的AC自动机状压DP,一看要求长度都一样,好像直接DP就行呀?
    然后写了最朴素的DP,dp[i][j]表示转移到第i个字符,目前能匹配上的状态为j的方案数,然后枚举下一位是什么,与所有字符串进行比较转移即可
    这样的复杂度是 $ O(26TLn*2^n) $ ,能有50分
    然后可以发现与所有字符串比较是很愚蠢的,进行了很多重复计算,我们可以预处理出每一位所有字符串匹配某个字符的结果,压在一个int里,转移时直接按位与即可
    这样复杂度是
    $ O(26TL*2^n) $ ,能有70分
    然后你把它数字带进去发现,它乘出来是26*5*50*2^15约等于2e8,这是什么意思?这意思就是稍微卡一卡就能过了。
    DP怎么稍微卡一卡呢?你想DP倒过来就是记忆化搜索,搜索可以剪枝啊,于是我们尝试剪一剪枝。
    怎么剪枝呢?加上如果在遍历到某个状态dp[i][j]时,如果dp[i][j]==0就不转移
    事实上这个效果好得出奇,速度快了10倍都不止,至此获得100分
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <string>
     6 #include <cstring>
     7 #include <cmath>
     8 #include <map>
     9 #include <stack>
    10 #include <set>
    11 #include <vector>
    12 #include <queue>
    13 #include <time.h>
    14 #define eps 1e-7
    15 #define INF 0x3f3f3f3f
    16 #define MOD 1000003
    17 #define rep0(j,n) for(int j=0;j<n;++j)
    18 #define rep1(j,n) for(int j=1;j<=n;++j)
    19 #define pb push_back
    20 #define set0(n) memset(n,0,sizeof(n))
    21 #define ll long long
    22 #define ull unsigned long long
    23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
    24 #define max(a,b) (a>b?a:b)
    25 #define min(a,b) (a<b?a:b)
    26 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
    27 #define TO(j) printf(#j": %d
    ",j);
    28 //#define OJ
    29 using namespace std;
    30 const int MAXINT = 100010;
    31 const int MAXNODE = 100010;
    32 const int MAXEDGE = 2*MAXNODE;
    33 char BUF,*buf;
    34 int read(){
    35     char c=getchar();int f=1,x=0;
    36     while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
    37     while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    38     return f*x;
    39 }
    40 char get_ch(){
    41     char c=getchar();
    42     while(!isalpha(c)) c=getchar();
    43     return c;
    44 }
    45 //------------------- Head Files ----------------------//
    46 
    47 int dp[51][1<<15],n,k,l,cnt[1<<15];
    48 unsigned int val[51][26];
    49 char s[15][60];
    50 void get_input();
    51 void work();
    52 int main() {
    53     int T=read();
    54     rep1(i,(1<<15)-1){
    55         cnt[i]=cnt[i-(i&-i)]+1;
    56     }
    57     while(T--){
    58         get_input();
    59         work();
    60     }
    61     return 0;
    62 }
    63 void work(){
    64     int mx = (1<<n);
    65     memset(val,0xffff,sizeof(val));
    66     rep1(i,l){
    67         rep0(j,26){
    68             rep0(k,n){
    69                 if(s[k][i]!='?'&&s[k][i]!='a'+j) val[i][j]&=(~(1<<k));
    70             }
    71         }
    72     }
    73     dp[0][(1<<n)-1] = 1;
    74     rep0(i,l){
    75         rep0(j,mx){
    76             if(dp[i][j]==0) continue;
    77             rep0(k,26){
    78                 int t = j;
    79                 t&=val[i+1][k];
    80                 dp[i+1][t]+=dp[i][j];
    81                 dp[i+1][t]%=MOD;
    82             }
    83         }
    84     }
    85     ll ans = 0;
    86     rep0(i,mx) if(cnt[i]==k) ans+=dp[l][i];
    87     printf("%lld
    ",ans%MOD);
    88 }
    89 void get_input(){
    90     memset(dp,0,sizeof(dp));
    91     n=read();k=read();
    92     rep0(i,n) scanf("%s",s[i]+1);
    93     l=strlen(s[0]+1);
    94 }
    
    
    
     
    
    
  • 相关阅读:
    Java SE 第十一讲(面向对象之封装)续二
    Java SE 第二十六讲 包与导入语句剖析
    Java SE 第三十一,二,三 Java数组剖析,Java数组内存地址解析
    Java SE 第三十四,五,六讲 Array类解析及数组疑难剖析,冒泡排序,交换排序以及快速排序
    Java SE 第三十八,九,四十,四十一,四十二,三四IDE详细介绍,ArrayList源代码深入剖析,L
    java高效的获取指定的精度的double数
    C++ 字符常量
    C++ endl
    C++基本数据类型
    vs2005的treeview简单使用之无限级别菜单建立
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6932869.html
Copyright © 2020-2023  润新知