标签:c++ 字符 return == bit pop 题目 方法 out
只讲解题方法,不讲题目题意
代码风格为个人喜好,请体谅
bzoj 1879 状态压缩dp -
设g[i][j]表示匹配到i位该位字符选j的集合
设f[i][j]为匹配打i位,集合位j的方案数
枚举每一位的字符得出g[i][j]
f[i][j]->f[i+1][j&g[i][ch]]
答案即为
sigma{f[len][set(popcount1==k)]}
复杂度为 o(set*n*len)=o(2^15*15*50)
#include<bits/stdc++.h>
using namespace std;
const int mod= (int) 1e6 + 3 , N = 52 ;
int n,k,ans=0;
int g[N][100],f[N][(1<<15)+20],len;
char s[20][N];
int count(int x) {
int ans=0;for(;x;ans+=(x&1),x>>=1);return ans;
}
void add(int &x,int y) {x+=y;for(;x>=mod;x-=mod);}
main() {
int t;
for(scanf("%d",&t);t;t--) {
memset(g,0,sizeof(g));ans=0;memset(f,0,sizeof(f));
cin>>n>>k;
for(int i=0;i<n;i++) scanf("%s",s[i]);len =strlen(s[0]);
for(int i=0;i<n;i++)
for(int j=‘a‘;j<=‘z‘;j++)
for(int l=0;l<len;l++) if(s[i][l]==‘?‘||s[i][l]==j)
g[l][j-‘a‘]|=(1<<i);
f[0][(1<<n)-1]=1;
for(int i=0;i<len;i++)
for(int j=0;j<(1<<n);j++) if(f[i][j])
for(int ch=‘a‘;ch<=‘z‘;ch++)
add(f[i+1][g[i][ch-‘a‘]&j],f[i][j]);
for(int j=0;j<(1<<n);j++) if(count(j)==k) add(ans,f[len][j]);
cout<<ans<<"\n";
}
}
标签:c++ 字符 return == bit pop 题目 方法 out
原文地址:http://www.cnblogs.com/foreverpiano/p/bzoj.html