Description
德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。
这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。
有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。
结果比尔吉沃特领土太小,只有长为n宽为m共计n*m块土地,其中有些土
地标记为0表示为高山峻岭或者深海湖泊,英雄们无法在其中站立,只有标
记为1的土地才能容纳一个英雄。德玛西亚的英雄们战斗时有一个特点,他
们不希望队友站在自己旁边显得很暧昧。请问最多能有多少种安排德玛西
亚英雄的方法?
Solution
补题向,一点进来就看见状压dp关键词,看数据范围 确实也是状压dp
考虑几种情况就可以了:
- 列不能连续1, 通过枚举上下行的状态,
为 true 的话就是有连续的1
- 行不能连续1,通过检验
为 true 的话就是有连续的1
- 和原图的0不能放,通过记录每一行的二进制状态,与当前状态
有
的话就是不相矛盾
注意多组数据!!还有数组记得开够!!
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
const int mod = 100000000;
const int N = 5e5 + 5;
typedef long long ll;
int mp[105];
int n, m;
int dp[105][105];
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
while(cin >> n >> m) {
memset(mp, 0, sizeof(mp));
for(int i = 1; i <= n; i++) {
for(int j = 0; j < m; j++) {
int x;
cin >> x;
mp[i] = (mp[i] << 1) + x;
}
}
dp[0][0] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 0; j < (1 << m); j++) {
if(j & (j >> 1)) continue; // 有连续的1
if((j & mp[i]) != j) continue; // 跟原图矛盾了
for(int k = 0; k < (1 << m); k++) { // 枚举上一行情况
if(j & k) continue;
dp[i][j] += dp[i - 1][k];
dp[i][j] %= mod;
}
}
}
ll ans = 0;
for(int i = 0; i < (1 << m); i++) {
ans += dp[n][i];
ans %= mod;
}
cout << ans << "\n";
}
return 0;
}

京公网安备 11010502036488号