set(NOIP模拟赛Round 4)
Posted ghostfly233
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了set(NOIP模拟赛Round 4)相关的知识,希望对你有一定的参考价值。
这题很神奇,对吧。
标程还理解了好久,才明白。
这道题需要用状压DP。首先我们看到总共只有15个字符串,所以可以用hash存储状态。
然后我们还需要一维用来存储DP到第几个字符。
所以dp[i][j]表示填到第i位后满足字符串的状态为j的个数;
一开始我们将一个统计数定义为nj=j(j为状态);
每次更新答案的时候只要从a到z枚举一遍,如果有不符合的地方那么nj-当前字符串所对应的二进制位(nj-=1<<l)
统计答案的时候我们只需要for一遍,看看是否有一种状态的符合字符串的个数刚好为k,将dp答案加入总答案即可。
下面贴代码
#include<iostream> #include<cstdio> #include<cstring> #define mod 1000003 #define mo(x)((x>=mod)?x-mod:x) #define match(a,b)((a==‘?‘)||(b==‘?‘)||(a==b)) using namespace std; char str[16][51]; int dp[51][1<<15]; int n,k,ans; int main(){ // freopen("set.in","r",stdin); // freopen("set.out","w",stdout); scanf("%d%d",&n,&k); for(int i=0;i<n;i++)scanf("%s",str[i]); int qaq=strlen(str[0]); dp[0][(1<<n)-1]=1; for(int i=0;i<qaq;i++) for(int j=1;j<(1<<n);j++) if(dp[i][j]) { for(int k=‘a‘;k<=‘z‘;k++) { int nj=j; for(int l=0;l<n;l++) { if(((j>>l)&1)&&(!match(str[l][i],k))) nj-=(1<<l); } dp[i+1][nj]=mo(dp[i+1][nj]+dp[i][j]); } } for(int i=0;i<(1<<n);i++) { int count=0; for(int j=0;j<n;j++)count+=((i>>j)&1); if(count==k)ans=mo(ans+dp[qaq][i]); } printf("%d\n",ans); // fclose(stdin); // fclose(stdout); }
以上是关于set(NOIP模拟赛Round 4)的主要内容,如果未能解决你的问题,请参考以下文章