@Acqua
2019-01-27T13:12:33.000000Z
字数 1462
阅读 1038
动态规划
给定一个的棋盘,要求在棋盘中放置尽量多的棋子。棋盘中部分位置不能放置,且如果位置放置了棋子,那么位置±,±,±,±都不能放置棋子。求最大可放置棋子数量。
如POJ3254,先预处理出每行的非法情况和合法情况,然后表示第行状态为,第行状态为的情况的答案。核心代码是枚举行、三重状态枚举。。
初始化:全为,把符合条件的赋为状态的数量,可以避免对的特判。
// La Pluie Froid#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N = 100 + 3, M = 70 + 3;int p[N], n, m, dp[N][M][M], pluie[M], cal[M], t;char s[15];int Cal(int x){int res = 0;while(x){if(x & 1) res++;x >>= 1;}return res;}void Geography(){scanf("%d %d", &n, &m);for(int i = 1; i <= n; i ++){scanf("%s", s + 1);for(int j = 1; j <= m; j++){p[i] |= (s[j] == 'H') << (j - 1);}}}void Legal(){for(int i = 0; i < (1 << m); i ++){if((i & (i << 1)) || (i & (i << 2))) continue;pluie[++ t] = i;}for(int i = 1; i <= t; i ++){if(p[1] & pluie[i]) continue;dp[1][i][1] = Cal(pluie[i]); // 此处第三维的含义是:第i-1行全为0的情况在pluie数组中坐标为1。}}int main(){Geography();memset(dp, -1, sizeof(dp));Legal();for(int i = 2; i <= n; i ++){for(int j = 1; j <= t; j ++){if(pluie[j] & p[i]) continue;for(int k = 1; k <= t; k ++){if(pluie[k] & p[i - 1]) continue;if(pluie[j] & pluie[k]) continue;for(int l = 1; l <= t; l ++){if(pluie[l] & p[i - 2]) continue;if(pluie[j] & pluie[l]) continue;if(pluie[k] & pluie[l]) continue;if(dp[i - 1][k][l] == -1) continue;dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + Cal(pluie[j]));}}}}int ans = 0;for(int i = 1; i <= t; i++){for(int j = 1; j <= t; j++){ans = max(ans, dp[n][i][j]);}}printf("%d", ans);return 0;}