dp[i][j][k] i代表此层用的状态序号 j上一层用的状态序号 k是层数&1(滚动数组)
标准流程 先预处理出所有合法数据存在status里 然后独立处理第一层 然后根据前一层的max推下一层
由于最多只有60多种状态 所以这其实就是个大暴力 其实还不慢
关于为什么要反义输入地图 因为我懒得写一个地图匹配状态函数了 所以直接让地图反义匹配状态
应该算是比较简单的状压DP
然而我还是写残了WA了两次orz
#include <iostream> #include <string> #include <cstring> #include <vector> #include <algorithm> using namespace std; int size, status[110], num[110]; int n, m, maze[110], dp[110][110][2]; inline bool ok(int a){ return !((a & (a >> 1)) || (a & a >> 2)); } inline bool fit(int a, int b){ return !(a & b); } void init(){ size = 0; memset(num, 0, sizeof num); int top = 1 << m; for(int i = 0; i < top; ++i){ if(ok(i)){ status[size] = i; int tmp = i; while(tmp){ if(tmp & 1) num[size]++; tmp >>= 1; } ++size; //cout << i << ends << num[size] << endl; } } } int main() { while(cin >> n >> m){ init(); for(int i = 0; i < n; ++i){ string tmp; cin >> tmp; for(int j = 0; j < m; ++j){ maze[i] <<= 1; //地图要反义输入 maze[i] += (tmp[j] == 'H'); } //cout << maze[i] << endl; } memset(dp, 0, sizeof dp); for(int i = 0; i < size; ++i){ if(fit(status[i], maze[0])){ dp[i][0][0] = num[i]; //cout << status[i] << ends << num[i] << endl; } } for(int i = 1; i < n; ++i){ for(int j = 0; j < size; ++j){ if(fit(maze[i], status[j])){ for(int k = 0; k < size; ++k){ if(fit(status[j], status[k])){ int maxx = 0; for(int l = 0; l < size; ++l){ if(fit(status[j], status[l])){ maxx = max(maxx, dp[k][l][!(i&1)]); } } dp[j][k][i&1] = max(dp[j][k][i&1], maxx + num[j]); } } } } } int ans = 0; for(int i = 0; i < size; ++i){ for(int j = 0; j < size; ++j){ ans = max(ans, dp[i][j][!(n&1)]); } } cout << ans << endl; } return 0; }