和炮兵阵地相似,就是摆放规则有一些不同
dp[i][j][k] 第i行状态为j,i-1行状态为k时的士兵最大值
目测我年事已高,居然在预处理时,把1<<m写成了1<<n,TLE了3次才发现这个.....
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>ok;
bool suit[101][200];
int dp[101][200][200],n,m;
int one[200];
int map[101][11];
inline void init()
{
for(int i=0;i< 1<<m;i++)
{
if(i&(i>>2)) continue;
if(i&(i<<2)) continue;
ok.push_back(i);
}
}
inline void is_ok()
{
memset(suit,0,sizeof(suit));
for(int i=0;i<n;i++)
{
for(int j=0;j<ok.size();j++)
{
int now=ok[j];
int tag=1;
for(int k=0;k<m;k++)
{
if(map[i][k]==0&&(now&(1<<k)))
{
tag=0;break;
}
}
if(tag) suit[i][j]=1;
}
}
}
inline int getOne(int i)
{
int ans=0;
while(i) ans+=i%2,i/=2;
return ans;
}
int main()
{
memset(one,-1,sizeof(one));
while(~scanf("%d%d",&n,&m))
{
ok.clear();
init();
for(int i=0;i<ok.size();i++)
{
if(one[i]==-1)
one[i]=getOne(ok[i]);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&map[i][j]);
is_ok();
int ans=0;
memset(dp,-1,sizeof(dp));
for(int i=0;i<ok.size();i++)
{
if(suit[0][i])
{
dp[0][i][0]=one[i];
ans=max(ans,dp[0][i][0]);
}
}
for(int i=1;i<n;i++)
{
for(int j=0;j<ok.size();j++)
{
if(!suit[i][j]) continue;
int now=ok[j];
for(int k=0;k<ok.size();k++)
{
if(!suit[i-1][k]) continue;
int now1=ok[k];
if(now&(now1<<1)) continue;
if(now&(now1>>1)) continue;
for(int r=0;r<ok.size();r++)
{
int now2=ok[r];
if(now&now2) continue;
if(dp[i-1][k][r]==-1) continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][r]+one[j]);
ans=max(ans,dp[i][j][k]);
}
}
}
}
printf("%d\n",ans);
}
}