• 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 }
  • 相关阅读:
    安装mysql警告 warning: mysql-community-server-5.7.19-1.el6.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY
    RPM方式安装MySQL5.6
    CentOS7安装MySQL冲突和问题解决小结
    Linux(64) 下 Tomcat + java 环境搭建
    自写Jquery插件 Combobox
    自写Jquery插件 Datagrid
    自写Jquery插件 Menu
    scrapy 中间件
    提高scrapy爬取效率配置
    scrapy基于请求传参实现深度爬取
  • 原文地址:https://www.cnblogs.com/refun/p/8877245.html
Copyright © 2020-2023  润新知