链接:登录—专业IT笔试面试备考平台_牛客网
很经典了。。。也算得上是一道板子题了
没有过多可以描述的,枚举每一行的合法状态,然后一次枚举上一行,上上一行,要求状态不矛盾。
可以用vector来做一个预处理,然后
因为每一层都是只有满足地图条件并且不会自矛盾才能有非0的dp值,所以每一次除了枚举这一行要将当前状态与地图进行对比外,它的上一行,上上一行都不需要再与地图进行对比了。
最后如果按状态开1<<10位的数组的话,三维吃不消,可以做一个小优化,打表发现合法状态也就六十几个,所以dp数组的后两维只开70也就够了,不过这样的话,dp里面就不再是对应的状态了,而是对应的状态的编号(因为是编号只有六十几个,而不是状态本身);体现在代码中
for(ll i=1;i<=n;++i){
for(ll q=0;q<vt.size();++q){//枚举当前行所有状态
ll st=vt[q];
if((st&mapp[i])!=st) continue;//与地图对比
for(ll w=0;w<vt.size();++w){//枚举上一行
ll st1=vt[w];
if(st1&st) continue;
// if((st1&mapp[i-1])!=st1) continue;//与地图对比
for(ll e=0;e<vt.size();++e){
ll st2=vt[e];
if(st1&st2) continue;
if(st&st2) continue;
// if((st2&mapp[i-2])!=st2) continue;//与地图对比
dp[i][q][w]=max(dp[i][q][w],num[q]+dp[i-1][w][e]);
(这里就是用q、w来对st1和st2了)
ans=max(ans,dp[i][q][w]);
}
}
}
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,ans;
ll mapp[110];
char k;
ll dp[110][70][70];//第i行状态为j,第i-1行状态为k的最大士兵数
vector<ll> vt;//存合法状态
vector<ll> num;
ll calc(ll x){
ll num=0;
while(x)
{
if(x&1) num++;
x>>=1;
}
return num;
}
int main()
{
cin>>n>>m;
ans=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
cin>>k;
mapp[i]*=2;
if(k=='P') mapp[i]++;
}
}
for(ll i=0;i<(1<<m);++i){
if(i&(i<<1)) continue;
if(i&(i<<2)) continue;
// if(i&(i>>1)) continue;
// if(i&(i>>2)) continue;
vt.push_back(i);//枚举并存放合法状态
num.push_back(calc(i));
}
for(ll i=1;i<=n;++i){
for(ll q=0;q<vt.size();++q){//枚举当前行所有状态
ll st=vt[q];
if((st&mapp[i])!=st) continue;//与地图对比
for(ll w=0;w<vt.size();++w){//枚举上一行
ll st1=vt[w];
if(st1&st) continue;
// if((st1&mapp[i-1])!=st1) continue;//与地图对比
for(ll e=0;e<vt.size();++e){
ll st2=vt[e];
if(st1&st2) continue;
if(st&st2) continue;
// if((st2&mapp[i-2])!=st2) continue;//与地图对比
dp[i][q][w]=max(dp[i][q][w],num[q]+dp[i-1][w][e]);
ans=max(ans,dp[i][q][w]);
}
}
}
}
cout<<ans<<endl;
return 0;
}