#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
int a[111];//将每一行处理为一串二进制数
int num[1<<10];//预处理数组
int dp[3][1<<10][1<<10];//point!!滚动数组,防止MLE
int getnum(int x)
{
int ret = 0;
while(x)
{
if(x&1) ++ret;
x >>= 1;
}
return ret;
}
int main()
{
int i, j, R, S, T;//R:当前行,S:上一行,T:上上一行
char ch;
cin >> n >> m;
memset(a, 0, sizeof(a));
for(i = 0; i < n; ++i)
for(j = 0; j < m; ++j)
{
cin >> ch;
a[i] <<= 1;
a[i] += (ch=='H'?1:0);
}
for(i = 0; i < (1<<m); ++i) num[i]=getnum(i);//初始化num数组
for(R = 0; R < (1<<m); ++R)//初始化第一行
if(!(R&a[0]) && !(R&(R<<1)) && !(R&(R<<2)))
dp[0][R][0] = num[R];
for(S = 0; S < (1<<m); ++S)//初始化第二行
for(R = 0; R < (1<<m); ++R)
if(!(R&S) && !(R&a[1]) && !(R&(R<<1)) && !(R&(R<<2)) && !(S&a[0]) && !(S&(S<<1)) && !(S&(S<<2)))
dp[1][R][S] = num[R] + num[S];
for(i = 2; i < n; ++i)//从第三行开始枚举行数
for(T = 0; T < (1<<m); ++T)//枚举上上行
{
if(T&a[i-2] || T&(T<<1) || T&(T<<2)) continue;
for(S = 0; S < (1<<m); ++S)//枚举上一行
{
if(S&a[i-1] || S&(S<<1) || S&(S<<2) || T&S) continue;
for(R = 0; R < (1<<m); ++R)//枚举当前行
{
if(R&a[i] || R&(R<<1) || R&(R<<2)|| R&T || R&S)
continue;
dp[i%3][R][S] = max(dp[i%3][R][S], dp[(i-1)%3][S][T]+num[R]);//更新状态
}
}
}
int ans = 0;
for(S = 0; S < (1<<m); ++S)
for(R = 0; R < (1<<m); ++R)
ans = max(ans, dp[(n-1)%3][R][S]);
printf("%d\n", ans);
return 0;
}
洛谷P2704_状压dp
最新推荐文章于 2023-01-18 22:57:39 发布
本文详细解析了洛谷平台上的P2704题目,通过使用动态规划和状态压缩的技术来求解问题。文章深入探讨了如何将问题转化为二进制表示,并利用动态规划的状态转移方程进行优化,降低时间复杂度,提高算法效率。
摘要由CSDN通过智能技术生成