德玛西亚万岁
https://ac.nowcoder.com/acm/problem/15034
个人体会:题目卡错,多写半年(忘记取模和多组数据QAQ)
思路:通过题目的描述,又是给棋盘数据范围又20不到,肯定是状压dp
状态表示:
dp[i][j]:前i行中,且第i行的放置状态为j的所有方法的cnt
状态计算:
dp[i][j] += dp[i - 1][k](前提相邻行的士兵不能相邻,即j & k == 0)
状态dp的一般流程:设置好状态表示和计算后,先预处理出的合法状态,本题中对于任意一行,其合法条件为
1.棋盘为0的位置不放置士兵,即(g[i] & j == g[i]
2.同一排士兵不能相邻 即((j >> 1) & j) == 0 && ((j << 1) & j))
AC代码
#include <bits/stdc++.h> using namespace std; #define IO std::ios::sync_with_stdio(false); cin.tie(0) #define ll long long #define ull unsigned long long #define SZ(x) ((int)(x).size()) #define all(x) (x).begin(), (x).end() #define rep(i, l, r) for (int i = l; i <= r; ++i) #define per(i, l, r) for (int i = l; i >= r; --i) #define mset(s, _) memset(s, _, sizeof(s)) #define mcpy(s, _) memcpy(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define vi vector<int> #define vpii vector<pii> #define mp(a, b) make_pair(a, b) #define pll pair <ll, ll> #define fir first #define sec second #define inf 0x3f3f3f3f inline int lowbit(int x) {return x & -x;} template< typename T > inline void get_min(T &x, T y) {if(y < x) x = y;} template< typename T > inline void get_max(T &x, T y) {if(x < y) x = y;} inline int read() { int x = 0, f = 0; char ch = getchar(); while (!isdigit(ch)) f |= ch == '-', ch = getchar(); while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar(); return f ? -x : x; } template<typename T> inline void print(T x) { if (x < 0) putchar('-'), x = -x; if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } template<typename T> inline void print(T x, char let) { print(x), putchar(let); } const int N = 15, M = 1e7 + 10, mod = 100000000; int n, m; int g[N]; ll dp[N][1 << N]; vi leg[N]; void init() { mset(dp, 0); mset(g, 0); rep(i, 0, n + 1) leg[i].clear(); } int main() { while(cin >> n >> m) { init(); for(int i = 1; i <= n; i ++ ) { for(int j = 1; j <= m; j ++ ) { int t; cin >> t; g[i] += (t << (j - 1)); } } for(int i = 1; i <= n + 1; i ++ ) { for(int j = 0; j < (1 << m); j ++ ) { if((g[i] | j) == g[i] && ((j << 1) & j) == 0 && ((j >> 1) & j) == 0) { leg[i].pb(j); if(i == 1) dp[1][j] = 1; } } } for(int i = 2; i <= n + 1; i ++ ) { for(auto j : leg[i]) { for(auto k : leg[i - 1]) { if((j & k) == 0) { dp[i][j] = (dp[i][j] + dp[i - 1][k]) % mod; } } } } cout << dp[n + 1][0] << endl; } return 0; }