冬马党
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
终于到了冬马党与雪菜党决战的时候了,为了方便,他们的决战之地可看成一个n×m矩阵。
决战前夜,冬马党安插在雪菜党中的内线告诉白学家Kuros
,雪菜党已经在他们的决战之地埋下了地雷。
白学家Kuros
根据多年来扫雷的经验,推测出雪菜党一定不会在相邻的格子里都放地雷。(两个格子相邻指它们共享一条边)并且,根据先遣部队的探查,某些格子的土地非常坚硬,是不可能埋地雷的。
为了冬马党最终的胜利,Kuros
想知道,雪菜党总共有多少种方案来放地雷。
Input
输入第一行为两个整数n,m,表示决战之地的大小。(1≤n≤12,1≤m≤12)
接下来n行,每行m个数,0表示该土地不能放地雷,1表示该土地可以埋地雷。
Output
一行,一个整数,表示总的方案数,答案取100000000的余数。
Sample input and output
Sample Input | Sample Output |
---|---|
2 3 1 1 1 0 1 0 |
9 |
Source
2014 UESTC Training for Dynamic Programming
解题报告
f(i,j) 表示第i行摆放情况为j的方案数.
用一个dfs进行转移.注意情况:
1.上一行的这个位置已经放了地雷,那么这一行的这里肯定不能再放
2.题目明确禁止这行的这个位置不允许放地雷.
因为我的dfs没有检查同一行两枚地雷相同的情况(非法),所以转移的时候j必须合法,最后答案计数的时候j也必须合法.
最重要的是。。。不要爆了long long(我挂了两发。。)
代码用了滚动数组进行优化~
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 typedef long long ll; 6 using namespace std; 7 const ll mod = 100000000; 8 ll f[2][1 << 13]; 9 bool g[15][15]; 10 int n,m,r,cur=0; 11 12 void dfs(int pos,int val,ll add) 13 { 14 if (pos == -1) 15 f[cur][val] = (f[cur][val] + add) % mod; 16 else 17 { 18 if (val >> pos & 1 || !g[r][pos]) //上一行的这个位置已经放了地雷 / 这个地方不允许放地雷 19 dfs(pos-1,val & ~(1 << pos),add); 20 else 21 { 22 dfs(pos-1,val | (1 << pos),add); 23 dfs(pos-1,val,add); 24 } 25 } 26 } 27 28 29 bool check(int x) 30 { 31 int pre = 0; 32 for(int i = 0 ; i < m ; ++ i) 33 { 34 int newx = x >> i & 1; 35 if (newx && pre) 36 return false; 37 pre = newx; 38 } 39 return true; 40 } 41 42 int main(int argc,char *argv[]) 43 { 44 memset(g,true,sizeof(g)); 45 memset(f,0,sizeof(f)); 46 scanf("%d%d",&n,&m); 47 for(int i = 0 ; i < n ; ++ i) 48 for(int j = 0 ; j < m ; ++ j) 49 { 50 int temp; 51 scanf("%d",&temp); 52 if (!temp) 53 g[i][j] = false; 54 } 55 r = 0; 56 dfs(m-1,0 , 1); 57 for(int i = 1 ; i < n ; ++ i) 58 { 59 cur ^= 1; 60 r = i; 61 for(int j = 0 ; j < (1 << m) ; ++ j) f[cur][j] = 0; 62 for(int j = 0 ; j < (1 << m) ; ++ j) 63 if (check(j)) 64 dfs(m-1,j,f[cur^1][j]); 65 } 66 int ans = 0; 67 for(int i = 0 ; i < (1 << m) ; ++ i) 68 if (check(i)) 69 ans = (ans + f[cur][i]) % mod; 70 printf("%lld ",ans % mod); 71 return 0; 72 }