啥?你说这是水题?
你还别说它就是个水题
那我为啥还要做?
因为我正要开始学呢呀
好的开始
题意:给你个矩阵,有的地方可以放牛有的不能,任意两头牛不能挨着,有多少种放法(一头不放当然也算)
好的所谓状压
就是将各种可以以1,0表示的图压成一个二进制数
比如
1 0 1 1 0 1 0
你就可以压成186
然后我们就可以愉快地开始了
第一步
因为不允许挨着,所以搜出一行上所有可能的放置方法
void dfs(int s,int pla)//搜到了第几位,当前状态 { if(pla>n)//搜完一整行的一种状态,保存 { scount++; sta[scount]=s; return; } dfs(s,pla+1);//pla位置上不放 dfs(s+(1<<(pla-1)),pla+2);//放 }
搜出所有可能放法之后
你就可以开始dp了
按照它的要求走就行
1 for(int i=1;i<=m;i++)for(int j=1;j<=n;j++) 2 { 3 scanf("%d",&stain); 4 allow[i]|=((stain^1)<<(j-1));//不能放的标记成1(自行思考一下为什么不是标成0) 5 } 6 dfs(0,1); 7 dp[0][0]=1; 8 for(int i=1;i<=m;i++)//每一行 9 { 10 for(int s=1;s<=scount;s++)//枚举每一个可能状态 11 { 12 if(sta[s]&allow[i])//如果在这一行不允许这么放 13 { 14 dp[i][sta[s]]=0; 15 continue; 16 } 17 for(int ss=1;ss<=scount;ss++)//枚举上一行所有可能状态 18 { 19 if(sta[s]&sta[ss])continue;//如果有挨着的那就不行 20 dp[i][sta[s]]+=dp[i-1][sta[ss]]; 21 dp[i][sta[s]]%=mo; 22 } 23 } 24 }
好的我就不放AC代码了...(被打死)
1 #include<cstdio> 2 #define ful 1<<12 3 #define mo 100000000 4 void swap(int &a,int &b) 5 { 6 int kkk=a; 7 a=b; 8 b=kkk; 9 } 10 int dp[13][ful],n,m,sta[ful],allow[13]; 11 int scount; 12 void dfs(int s,int pla) 13 { 14 if(pla>n) 15 { 16 scount++; 17 sta[scount]=s; 18 return; 19 } 20 dfs(s,pla+1); 21 dfs(s+(1<<(pla-1)),pla+2); 22 } 23 int main() 24 { 25 scanf("%d%d",&m,&n); 26 int stain; 27 for(int i=1;i<=m;i++)for(int j=1;j<=n;j++) 28 { 29 scanf("%d",&stain); 30 allow[i]|=((stain^1)<<(j-1)); 32 } 33 dfs(0,1); 37 dp[0][0]=1; 38 for(int i=1;i<=m;i++) 39 { 40 for(int s=1;s<=scount;s++) 41 { 42 if(sta[s]&allow[i]) 43 { 44 dp[i][sta[s]]=0; 46 continue; 47 } 48 for(int ss=1;ss<=scount;ss++) 49 { 50 if(sta[s]&sta[ss])continue; 51 dp[i][sta[s]]+=dp[i-1][sta[ss]]; 52 dp[i][sta[s]]%=mo; 53 } 54 } 55 } 58 int ans=0; 59 for(int s=1;s<=scount;s++) 60 { 61 ans+=dp[m][sta[s]]; 62 ans%=mo; 63 } 64 printf("%d",ans); 65 return 0; 66 }