// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方法数,完全对自己无语了。。。 // 不过,最后把get(S)改为1就ac啦~~~还是很开心的 // wa了无数发啊,哎。。。继续练吧。。。。 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <functional> #include <iostream> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <stack> #include <vector> #define ceil(a,b) (((a)+(b)-1)/(b)) #define endl '\n' #define gcd __gcd #define highBit(x) (1ULL<<(63-__builtin_clzll(x))) #define popCount __builtin_popcountll typedef long long ll; using namespace std; const int MOD = 1000000007; const long double PI = acos(-1.L); template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; } template<class T> inline T lowBit(const T& x) { return x&-x; } template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; } template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; } const int maxn = 15; int dp[maxn][1<<maxn]; int n,m; int state[maxn]; const int M = 1e8; bool ok(int x){ if (x&(x<<1)) return false; return true; } int get(int x){ int cnt = 0; while(x){ if (x&1) cnt++; x>>=1; } return cnt; } void init(){ int a; memset(state,0,sizeof(state)); for (int i=0;i<n;i++){ for (int j=0;j<m;j++){ scanf("%d",&a); if (!a){ state[i] = state[i] | (1<<j); } } } memset(dp,0,sizeof(dp)); for (int i=0;i<(1<<m);i++){ if (i&state[0]) continue; if (ok(i)){ dp[0][i] = 1; } } } void print(){ for (int i=0;i<n;i++){ for (int j=0;j<(1<<m);j++) printf("%d ",dp[i][j]); puts(""); } } void solve(){ for (int i=1;i<n;i++){ for (int S=0;S<(1<<m);S++){ if (!ok(S)) continue; if (S&state[i]) continue; for (int V=0;V<(1<<m);V++){ if (!ok(V)) continue; if (S&V) continue; if (V&state[i-1]) continue; dp[i][S] = (dp[i][S]+dp[i-1][V])%M; } } } // print(); int ans = 0; for (int i=0;i<(1<<m);i++) if (ok(i)) ans =(ans+dp[n-1][i])%M; printf("%d\n",ans); } int main() { //freopen("G:\\Code\\1.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ init(); solve(); } return 0; }
时间: 2024-10-13 01:48:30