标签:状态 20 600 int Fields Corn 状压 include dp
dp[i][j]表示第i行第j个状态时,前i行得到的方案数,该状态可由前一行的状态转移过来。
本题重点在于合法性检测:每一行都用一个二进制数表示,1.二进制数不能有相邻的1;2.要和原地图匹配;3.上下两行不能有冲突。
预处理地图时将0换成1,方便进行2号检测,用位运算&可以实现。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define mod 100000000 5 int m,n,top=0; 6 int state[600];//储存合法状态 7 int dp[20][600];//dp[i][j]表示第i行,第j种编号时,前i行的可行方案数 8 int cur[20]; 9 10 bool check(int x){//有相邻的1则不合法 11 if(x&x<<1) return 0; 12 return 1; 13 } 14 15 void init(){//记录所有没有相邻1的编号 16 top=0; 17 for(int i=0;i<1<<n;i++)//n个格子,2^n种情况 18 if(check(i)) state[++top]=i; 19 } 20 21 bool fit(int x,int k){ 22 if(x&cur[k]) return 0; 23 return 1; 24 } 25 26 void solve(){ 27 for(int j=1;j<=top;j++) 28 if(fit(state[j],1)) 29 dp[1][j]=1;//处理第1行 30 for(int i=2;i<=m;i++) 31 for(int j=1;j<=top;j++){//state[j]是i行的状态 32 if(!fit(state[j],i)) continue; 33 for(int k=1;k<=top;k++){//state[k]是i-1行的状态 34 if(!fit(state[k],i-1)) continue; 35 if(state[j]&state[k]) continue;//上下行有相邻1 36 dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; 37 } 38 } 39 } 40 41 int main(){ 42 while(~scanf("%d%d",&m,&n)){ 43 init(); 44 memset(dp,0,sizeof(dp)); 45 for(int i=1;i<=m;i++){ 46 cur[i]=0; 47 int num; 48 for(int j=1;j<=n;j++){ 49 scanf("%d",&num); 50 if(num==0) cur[i]+=(1<<(n-j));//0记录为1,方便检测 51 } 52 } 53 solve(); 54 int ans=0; 55 for(int j=1;j<=top;j++) 56 ans=(ans+dp[m][j])%mod; 57 printf("%d\n",ans); 58 } 59 return 0; 60 }
标签:状态,20,600,int,Fields,Corn,状压,include,dp 来源: https://www.cnblogs.com/yhxnoerror/p/16410783.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。