BZOJ 1879 [Sdoi2009]Bill的挑战 ——状压DP
本来打算好好写写SDOI的DP题目,但是忒难了,
太难了,就写的这三道题仿佛是可做的。
生在弱省真是兴奋。
这题目直接状压,f[i][j]表示匹配到i,状态集合为j的方案数,然后递推即可。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) const int md=1000003; int dp[2][1<<16],T,n,m,len,g[60][30],ans=0; char s[16][60]; void print(int x) { F(i,0,n-1) printf("%d",(x>>i)&1); } int main() { scanf("%d",&T); while (T--) { ans=0;memset(g,0,sizeof g); scanf("%d%d",&n,&m); F(i,0,n-1) scanf("%s",s[i]+1); len=strlen(s[1]+1); F(i,1,len) F(j,0,25) { F(k,0,n-1) if (s[k][i]=='?'||(s[k][i]-'a')==j) g[i][j]|=(1<<k); } int now=1,pre=0; memset(dp[now],0,sizeof dp[now]); dp[now][(1<<n)-1]=1; F(i,1,len) { now^=1; pre^=1; memset(dp[now],0,sizeof dp[now]); F(j,0,(1<<n)-1) if (dp[pre][j]) F(k,0,25) (dp[now][j&g[i][k]]+=dp[pre][j])%=md; } F(i,0,(1<<n)-1) { int t=i,cnt=0; while (t) {cnt+=(t&1);t>>=1;} if (cnt==m) (ans+=dp[now][i])%=md; } printf("%d\n",ans); } }