设
f[i][j][k(0/1)]
表示现在在点(i,j),在第i行只走了j一个点,经过的
′F′
个数奇偶性为k时最少时间。
设
l[i][j(0/1)][k(0/1)]
表示在当前行,从i左边的点t出发,经过j个
′F′
,由
f[pre][t][k]
更新来的最小时间。
设
r[i][j(0/1)][k(0/1)]
表示在当前行,从i右边的点t出发,经过j个
′F′
,由
f[pre][t][k]
更新来的最小时间。
然后
l
和
就可以通过分治做到
O(n2∗logn)
的复杂度。
不过这里有个问题,就是分治时当状态区间的中点无法被任何点更新时(无解)下一步取值区间的中点无法选择。
由于数据较水,因此取状态区间的中点可过。。。
还有由于代码写得太渣,自带了一个大常数。。。
#include <bits/stdc++.h>
using namespace std;
#define N 1100
#define cl(x) memset(x,0x3f,sizeof(x))
int n,m,ans,inf;
int ln,rn,vn,sn,no,nb,ns,nn,now,dir;
char s[N][N];
int f[N][N][2],l[N][2][2],r[N][2][2];
int cal(int x,int y)
{
if(s[x][y]=='B')return 0;
if(s[x][y]=='S')return 2;
return 1;
}
void upd(int &x,int y){x=min(x,y);}
void add(char c,int tp)
{
if(c=='B')nb+=tp;else if(c=='S')ns+=tp;else nn+=tp;
if(c=='O')no+=tp;if(c=='F')sn^=1;
}
void del(int x,int tp)
{
char c=s[now][x];
if(tp==dir)
vn-=nn+ns*2,add(c,-1);
else
{
add(c,-1);
if(c=='S')vn-=(nn+ns+nb+1)*2;
else if(c!='B')vn-=nn+ns+nb+1;
}
}
void ins(int x,int tp)
{
char c=s[now][x];
if(tp==dir)
add(c,1),vn+=nn+ns*2;
else
{
if(c=='S')vn+=(nn+ns+nb+1)*2;
else if(c!='B')vn+=nn+ns+nb+1;
add(c,1);
}
}
void move(int l,int r)
{
while(ln<l)del(ln,0),ln++;
while(ln>l)ln--,ins(ln,0);
while(rn>r)del(rn,1),rn--;
while(rn<r)rn++,ins(rn,1);
}
void solvel(int l1,int r1,int l2,int r2,int tp,int tp1)
{
if(l1>r1||l2>r2)return;
int mid=(l1+r1)>>1,pos=0;
for(int i=min(mid,r2);i>=l2;i--)
{
move(i+1,mid);
if(!no&&sn==tp1&&l[mid][tp][tp1]>f[now][i][tp^sn]+vn)
{
l[mid][tp][tp1]=f[now][i][tp^sn]+vn;
pos=i;
}
}
if(pos)
{
solvel(l1,mid-1,l2,pos,tp,tp1);
solvel(mid+1,r1,pos,r2,tp,tp1);
}
else
{
solvel(l1,mid-1,l2,mid-1,tp,tp1);
solvel(mid+1,r1,mid+1,r2,tp,tp1);
}
}
void solver(int l1,int r1,int l2,int r2,int tp,int tp1)
{
if(l1>r1)return;
int mid=(l1+r1)>>1,pos=0;
for(int i=max(mid,l2);i<=r2;i++)
{
move(mid,i-1);
if(!no&&sn==tp1&&r[mid][tp][tp1]>f[now][i][tp^sn]+vn)
{
r[mid][tp][tp1]=f[now][i][tp^sn]+vn;
pos=i;
}
}
if(pos)
{
solver(l1,mid-1,l2,pos,tp,tp1);
solver(mid+1,r1,pos,r2,tp,tp1);
}
else
{
solver(l1,mid-1,l2,mid-1,tp,tp1);
solver(mid+1,r1,mid+1,r2,tp,tp1);
}
}
int main()
{
freopen("tt.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
cl(l);cl(r);cl(f);inf=l[0][0][0];
for(int i=1;i<=m;i++)
if(s[n][i]=='H')
f[n][i][0]=l[i][0][0]=r[i][0][0]=0;
for(int i=n-1;i>=1;i--)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='O')continue;
int t=(s[i][j]=='F'),v=cal(i,j);
upd(f[i][j][t],min(l[j][0][0],l[j][0][1])+v);
upd(f[i][j][t],min(r[j][0][0],r[j][0][1])+v);
upd(f[i][j][t^1],min(l[j][1][0],l[j][1][1])+v);
upd(f[i][j][t^1],min(r[j][1][0],r[j][1][1])+v);
}
cl(l);cl(r);now=i;
ln=1;rn=0;vn=0;sn=0;no=0;nb=0;ns=0;nn=0;dir=0;
solvel(1,m,1,m,0,0);solvel(1,m,1,m,1,0);
solvel(1,m,1,m,0,1);solvel(1,m,1,m,1,1);
ln=1;rn=0;vn=0;sn=0;no=0;nb=0;ns=0;nn=0;dir=1;
solver(1,m,1,m,0,0);solver(1,m,1,m,1,0);
solver(1,m,1,m,0,1);solver(1,m,1,m,1,1);
}
ans=inf;
for(int i=1;i<=m;i++)
if(s[1][i]=='H')
ans=min(ans,f[1][i][1]);
if(ans==inf)return puts("Victory of Darkness"),0;
printf("%d\n",ans);
return 0;
}