POJ 1038 Bugs Integrated, Inc.(DFS + 三进制状压 + 滚动数组 思维)题解
题意:n*m方格,有些格子有黑点,问你最多裁处几张2 * 3(3 * 2)的无黑点格子。
思路:我们放置2 * 3格子时可以把状态压缩到三进制:
关于状压:POJ-1038 Bugs Integrated, Inc. (状压+滚动数组+深搜 的动态规划),写的很详细
所以我们直接枚举每一行的所有可能状态,并算出每种状态最大值。这样我们到最后只要找到n行所有状态最大值就行了。
代码:
#include<cmath> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 150 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; int dp[2][60000], ter[15]; int vis[160][15]; int t, n, m, k; int now[15], pre[15]; void getNow(int i){ for(int k = 1; k <= m; k++){ if(vis[i][k]){ now[k] = 2; } else{ if(pre[k] <= 1) now[k] = 0; else now[k] = 1; } } } int getSt(){ int ret = 0; for(int k = 1; k <= m; k++){ ret = ret * 3 + now[k]; } return ret; } void dfs(int i, int j, int num){ int nowSt; if(j > m){ nowSt = getSt(); dp[i % 2][nowSt] = max(dp[i % 2][nowSt], num); return; } // ▇ ▇ ▇ // ▇ ▇ ▇ if(j >= 3 && !now[j - 2] && !now[j - 1] && !now[j]){ now[j - 2] = now[j - 1] = now[j] = 2; nowSt = getSt(); dp[i % 2][nowSt] = max(dp[i % 2][nowSt], num + 1); dfs(i, j + 2, num + 1); now[j - 2] = now[j - 1] = now[j] = 0; } // ▇ ▇ // ▇ ▇ // ▇ ▇ if(j >= 2 && !now[j - 1] && !now[j] && !pre[j - 1] && !pre[j]){ now[j - 1] = now[j] = 2; nowSt = getSt(); dp[i % 2][nowSt] = max(dp[i % 2][nowSt], num + 1); dfs(i, j + 2, num + 1); now[j - 1] = now[j] = 0; } nowSt = getSt(); dp[i % 2][nowSt] = max(dp[i % 2][nowSt], num); dfs(i, j + 1, num); } int main(){ ter[0] = 1; for(int i = 1; i <= 12; i++){ ter[i] = ter[i - 1] * 3; } scanf("%d", &t); while(t--){ scanf("%d%d%d", &n, &m, &k); memset(vis, 0, sizeof(vis)); for(int i = 1; i <= k; i++){ int x, y; scanf("%d%d", &x, &y); vis[x][y] = 1; } //0 都可以,1 上一行不可以,2 都不可以 int temp = 0; for(int i = 1; i <= m; i++) temp = temp * 3 + 2; memset(dp[0], -1, sizeof(dp[0])); dp[0][temp] = 0; for(int i = 1; i <= n; i++){ memset(dp[i % 2], -1, sizeof(dp[0])); for(int st = 0; st < ter[m]; st++){ if(dp[(i + 1) % 2][st] == -1) continue; int tmp = st; for(int j = m; j >= 1; j--){ pre[j] = tmp % 3; tmp /= 3; } getNow(i); dfs(i, 1, dp[(i + 1) % 2][st]); } } int Max = -1; for(int i = 0; i < ter[m]; i++) Max = max(Max, dp[n % 2][i]); printf("%d\n", Max); } return 0; }