一,题意:
给定一个N*M的矩阵,矩阵每个格子中只可能有两个数字0,1,1表示该土地肥沃可以种草放牛。
0表示该土地不肥沃不可以种草放牛。且牛不能放在相邻的位置,问有多少种放牛的方法。
二,解析:
该题主要应用了图的位压缩成数的思想与递推的思想,即压缩dp。
三,代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> using namespace std; const int mod=100000000; int N,M; int graph[15]; int total[1<<13],Size; int dp[15][1<<13]; long long sum=0; void Search() {//记录下哪些数字合法 Size=0; for(int i=0; i<(1<<M); i++) { if(!(i&(i<<1)))//二进制1不相邻 total[Size++]=i; } } int main() { while(scanf("%d%d",&N,&M)!=EOF) { int key; memset(graph,0,sizeof(graph)); for(int i=0; i<N; i++) { for(int j=0; j<M; j++) { scanf("%d",&key); if(!key)//将矩阵每一行压缩成一个数,为了好计算我们将其取反 graph[i]=graph[i]|(1<<j); } } Search(); memset(dp,0,sizeof(dp)); for(int i=0;i<Size;i++) {//初始化的0行 if(!(total[i]&graph[0])) dp[0][total[i]]=1; } for(int i=1;i<N;i++) {//行循环 for(int j=0;j<Size;j++) {//该行可能合法的数字 if(total[j]&graph[i]) continue;//与原图不匹配 for(int k=0;k<Size;k++) {//向上一行匹配 if(dp[i-1][total[k]]&&(!(total[j]&total[k]))) dp[i][total[j]]=(dp[i][total[j]]+dp[i-1][total[k]])%mod; } } } sum=0; for(int i=0;i<Size;i++) {//最后一行求和 if(dp[N-1][total[i]]) sum=(sum+dp[N-1][total[i]])%mod; } cout<<sum<<endl; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/yu_zhi_bo_zhi_shui/article/details/47829277