zoukankan      html  css  js  c++  java
  • BZOJ1879:[SDOI2009]Bill的挑战(状压DP)

    Description

    Input

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

    Output

    如题

    Sample Input

    5
    3 3
    ???r???
    ???????
    ???????
    3 4
    ???????
    ?????a?
    ???????
    3 3
    ???????
    ?a??j??
    ????aa?
    3 2
    a??????
    ???????
    ???????
    3 2
    ???????
    ???a???
    ????a??

    Sample Output

    914852
    0
    0
    871234
    67018

    Solution

    第一眼数据范围:撞鸭状压DP没跑了
    而且连压什么都告诉你了,毕竟只有N能压
    状态设计很简单:f[i][S]该选第i列了,当前选中的行是集合S
    然后我后面就G了……搞了半天又是容斥又是各种判断乱搞只有20……
    其实预处理一下就非常好做了。
    预处理出g[第i列][j字母]=集合x
    表示j字母可以和集合x的第i位匹配(我第一次看的时候有点绕)
    然后就枚举当为集合x的时候第i位填j字母然后进行转移就好了
    果然我就是R1出题人说的"学数据结构学傻了"
    虽然我数据结构仍然辣鸡

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define MAXN (40001)
     5 using namespace std;
     6 int f[52][MAXN],g[52][31];
     7 int N,K,T,len,sum;
     8 char s[101][101];
     9 
    10 int main()
    11 {
    12     scanf("%d",&T);
    13     while (T--)
    14     {
    15         memset(f,0,sizeof(f));
    16         memset(g,0,sizeof(g));
    17         scanf("%d%d",&N,&K);
    18         for (int i=1; i<=N; ++i)
    19             scanf("%s",s[i]+1);
    20         len=strlen(s[1]+1);
    21         
    22         for (int i=1; i<=len; ++i)
    23             for (int j=0; j<26; ++j)
    24                 for (int k=1; k<=N; ++k)
    25                     if (s[k][i]=='?' || s[k][i]==j+'a')
    26                         g[i][j]|=(1<<k-1);
    27         
    28         sum=(1<<N)-1;
    29         f[0][sum]=1;            
    30         for (int i=1; i<=len; ++i)
    31             for (int j=0; j<=sum; ++j)
    32                 if (f[i-1][j])//不加这个判断会TLE,可能是%太多了? 
    33                     for (int k=0; k<26; ++k)
    34                         (f[i][j&g[i][k]]+=f[i-1][j])%=1000003;
    35 
    36         int ans=0;
    37         for (int i=0; i<=sum; ++i)
    38         {
    39             int x=i,cnt=0;
    40             while (x)
    41             {
    42                 if (x&1) cnt++;
    43                 x>>=1;
    44             }
    45             if (cnt==K) (ans+=f[len][i])%=1000003;
    46         }
    47         printf("%d
    ",ans);
    48     }
    49 }
  • 相关阅读:
    将vue文件script代码抽取到单独的js文件
    git pull 提示错误:Your local changes to the following files would be overwritten by merge
    vue和uniapp 配置项目基础路径
    XAMPP Access forbidden! Access to the requested directory is only available from the local network.
    postman与newman集成
    postman生成代码段
    Curl命令
    POST方法的Content-type类型
    Selenium Grid 并行的Web测试
    pytorch转ONNX以及TnesorRT的坑
  • 原文地址:https://www.cnblogs.com/refun/p/8877245.html
Copyright © 2011-2022 走看看