其他分享
首页 > 其他分享> > SDOI 2009 Bill的挑战 【动态规划】

SDOI 2009 Bill的挑战 【动态规划】

作者:互联网

看数据范围发现n异常的小,于是想到装压

map[i][j]表示第i个字符填j时与那些匹配串符合

dp[i][j] 表示第i个字符,匹配的情况为j,有多少方案

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define gi get_int()
const int MAXN = 60, LIM = 1 << 16;
int get_int()
{
  int x = 0, y = 1;
  char ch = getchar();
  while (!isdigit(ch) && ch != '-')
    ch = getchar();
  if (ch == '-')
    y = -1, ch = getchar();
  while (isdigit(ch))
    x = x * 10 + ch - '0', ch = getchar();
  return x * y;
}

int map[MAXN][26], dp[2][LIM];

int countBit(int x)
{
  int ans = 0;
  while (x != 0) {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}

int main()
{
  freopen("code.in", "r", stdin);
  freopen("code.out", "w", stdout);

  int T = gi;
  while (T--) {
    memset(dp, 0, sizeof(dp));
    memset(map, 0, sizeof(map));
    int n = gi, k = gi, size;
    for (int i = 0; i < n; i++) {
      std::string str;
      std::cin >> str;
      size = str.size();
      for (int j = 0; j < size; j++) {
        if (str[j] == '?')
          for (int k = 0; k < 26; k++)
            map[j][k] |= 1 << i;
        else
          map[j][str[j] - 'a'] |= 1 << i;
      }
    }
    for (int i = 0; i < 26; i++) {
      dp[0][map[0][i]]++;
    }
    for (int i = 0; i < size - 1; i++) {
      for (int j = 0; j < (1 << n); j++) {
        for (int k = 0; k < 26; k++)
          dp[!(i & 1)][j] = 0;
      }
      for (int j = 0; j < (1 << n); j++) {
        for (int k = 0; k < 26; k++)
            (dp[!(i & 1)][j & map[i + 1][k]] += dp[i & 1][j]) %= 1000003;
      }
    }
    int ans = 0;
    for (int i = 0; i < (1 << n); i++) {
      if (countBit(i) == k)
        (ans += dp[1 & (size - 1)][i]) %= 1000003;
    }
    std::cout << ans << std::endl;
  }

  return 0;
}

标签:map,2009,SDOI,int,Bill,str,include,gi,size
来源: https://www.cnblogs.com/enisP/p/14813985.html