思路
状压dp,dp[i][j]:表示到第i行,状态为j的方案数。预处理出每一行所有的可能的选法。
转移方程:dp[i][j] += d[i-1][k],j与k不冲突。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 7 using namespace std; 8 9 const int mod = 1e9; 10 int a[15][15],sta[15][10010],dp[15][10010]; 11 int n,m; 12 13 inline int read() { 14 int x = 0,f = 1;char ch = getchar(); 15 for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1; 16 for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0'; 17 return x * f; 18 } 19 20 void getsta() { 21 int t = (1 << m) - 1;bool flag; 22 for (int i=1; i<=n; ++i) { 23 for (int j=0; j<=t; ++j) { 24 flag = true; 25 for (int k=0; k<m; ++k) 26 if (!a[i][m-k] && ((1<<k)&j)) {flag = false;break;} 27 if (!flag) continue; 28 if (j & (j<<1)) continue; 29 sta[i][++sta[i][0]] = j; 30 } 31 } 32 } 33 void getdp() { 34 for (int i=1; i<=sta[1][0]; ++i) dp[1][i] = 1; //dp[1][i] not dp[1][sta[1][i]] 35 for (int i=2; i<=n; ++i) 36 for (int j=1; j<=sta[i][0]; ++j) 37 for (int k=1; k<=sta[i-1][0]; ++k) { 38 if (sta[i][j] & sta[i-1][k]) continue; 39 dp[i][j] += dp[i-1][k]; 40 if (dp[i][j] > mod) dp[i][j] %= mod; 41 } 42 int ans = 0; 43 for (int i=1; i<=sta[n][0]; ++i) { 44 ans += dp[n][i]; 45 if (ans > 0) ans %= mod; 46 } 47 cout << ans; 48 } 49 50 int main() { 51 n = read(),m = read(); 52 for (int i=1; i<=n; ++i) 53 for (int j=1; j<=m; ++j) 54 a[i][j] = read(); 55 getsta(); 56 getdp(); 57 return 0; 58 }
http://poj.org/problem?id=3254