题意:给你一个n*m的矩阵,有一些格子是好的一些是坏的,问你最多能剪出多少个2*2的正方形。(n,m<=10)
思路:正好前几天做过炮兵布阵,跟那题很类似(点击打开链接),注意判断下地形和状态是否冲突,地形和地形是
否冲突,因为是2*2的,所以跟三个方向有关和自身位置4个地方不能冲突。注意预处理合法状态时枚举到1<<(m-1)即
可,因为两边肯定有一个不行(因为假如1标志的是2*2的右下角,那么最左边的不可能标记为1)。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 105;
int dp[maxn][maxn], maze[maxn], status[maxn], num[maxn];
int t, n, m;
bool judgdMap(int i, int row) //判断row行的status[i]状态与地形是否冲突
{
int s = status[i];
if(maze[row]&s || maze[row]&(s<<1) || maze[row+1]&s || maze[row+1]&(s<<1)) return 0;
else return 1;
}
bool judgeSta(int a, int b) //判断status[a]和status[b]状态是否冲突
{
if((status[a]&status[b]) || ((status[a]<<1)&status[b]) || (status[a]&(status[b]<<1))) return 0;
return 1;
}
int main(void)
{
cin >> t;
while(t--)
{
scanf("%d%d", &n, &m);
memset(dp, 0, sizeof(dp));
memset(maze, 0, sizeof(maze));
for(int i = 1; i <= n; i++)
for(int j = 0; j < m; j++)
{
int x;
scanf("%d", &x);
if(!x) maze[i] += (1<<j);
}
int len = 0;
for(int i = 0; i < (1<<(m-1)); i++)
if(!(i&(i<<1)))
{
int t = i, cnt = 0;
while(t)
{
if(t%2) cnt++;
t /= 2;
}
num[len] = cnt;
status[len++] = i;
}
for(int i = 0; i < len; i++)
{
if(judgdMap(i, 1))
dp[1][i] = num[i];
}
for(int i = 2; i < n; i++)
{
for(int j = 0; j < len; j++)
{
if(!judgdMap(j, i)) continue;
for(int k = 0; k < len; k++)
{
if(!judgdMap(k, i-1) || !(judgeSta(j, k))) continue;
dp[i][j] = max(dp[i][j], dp[i-1][k]+num[j]);
}
}
}
int ans = 0;
for(int i = 0; i < len; i++)
ans = max(ans, dp[n-1][i]);
printf("%d\n", ans);
}
return 0;
}
本文介绍了一个优化算法,用于在一个n*m的矩阵中寻找最多可以剪裁出的2*2正方形数量。该算法通过状态压缩和动态规划实现,并详细解释了如何避免地形和状态间的冲突。
286

被折叠的 条评论
为什么被折叠?



