LeavingZzz @ 2020-01-17 09:40:33
20分现场
代码如下
#include<cstdio>
#include<algorithm>
using namespace std;
int sta[107][68],sum[107][68];
int DP[107][68];
int g[107],cnt[107];
char m[107][17];
int N,M,all;
void pre()
{
for(int i=1;i<=N;i++)
{
for(int j=0;j<=all;j++)
{
if(((j&(j<<2))==0)&&((j&(j<<1))==0)&&((j&g[i])==0))
{
sta[i][++cnt[i]]=j;
int x=j;
while(x)
{
sum[i][cnt[i]]++;
x-=x&(-x);
}
}
}
}
return ;
}
void print(int x)
{
if(x==0)
return ;
print(x>>1);
printf("%d",x%2);
return ;
}
int main()
{
scanf("%d%d",&N,&M);
int ans=0;
all=1<<M;all--;
for(int i=1;i<=N;i++)
scanf("%s",m[i]);
for(int i=1;i<=N;i++)
for(int j=0;j<M;j++)
{
if(m[i][j]=='H')
g[i]|=(1<<j);
}
pre();
cnt[0]=1;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=cnt[i-1];j++)
for(int k=1;k<=cnt[i];k++)
{
if(i>2)
{
for(int l=1;l<=cnt[i-2];l++)
{
if(((sta[i-1][j]&sta[i][k])==0)
&&((sta[i-2][l]&sta[i-1][j])==0)
&&((sta[i-2][l]&sta[i][k])==0)
&&DP[i-2][l]+sum[i-1][j]+sum[i][k]>DP[i][k])
DP[i][k]=DP[i-2][l]+sum[i-1][j]+sum[i][k];
}
}
else
{
if(((sta[i-1][j]&sta[i][k])==0)
&&sum[i][k]+DP[i-1][j]>DP[i][k])
DP[i][k]=DP[i-1][j]+sum[i][k];
}
}
}
for(int i=1;i<=cnt[N];i++)
ans=max(ans,DP[N][i]);
printf("%d",ans);
return 0;
}
by LeavingZzz @ 2020-01-17 09:42:19
这里的DP[i][j]意为第行以第j种状态时已经放下的炮兵数
sum[i][j]意为第i行第j种状态下的炮兵数量
主要思想是预处理出每一行所有不会在一行内相互攻击并且不与地图相冲突的方案 再将行与行之间的状态链接起来
sta[i][j]存储了第i行的第j种状态对应的数(状态压缩) 相互的sta[i][j]进行&运算来确定有没有冲突的炮兵
g[i] 保存了第i行因为地形冲突的地方也是通过&运算来确定是否冲突
by Trinitrotoluene @ 2020-01-17 13:36:14
怎么连样例都过不了。。。
by LeavingZzz @ 2020-01-19 16:00:45
@Trinitrotoluene 难受啊 我觉得好像没有问题,但是就是莫名要不得
by LeavingZzz @ 2020-01-19 16:01:33
@Trinitrotoluene 样例过了呀.....
by Trinitrotoluene @ 2020-01-19 19:46:33
。。。
by Trinitrotoluene @ 2020-01-19 19:47:10
你找别人问吧,这道题我还没做呢
by Minecraft万岁 @ 2020-03-31 09:45:35
大佬怎么哪里都能见到你啊 我也要学状压了(逃
by BotBw @ 2021-03-10 17:31:43
晕了同样的思路我也过不了,请问你是否解决了这个问题