[The 2011 ACM-ICPC Asia Chengdu Regional Contest]C.Construct the Great Wall

基于连通性状态压缩的动规。

CODE:

/*
PROGRAM: $PROGRAM
AUTHOR: Su Jiao
DATE: 2011-11-28
DESCRIPTION:
$DESCRIPTION
*/

#include <iostream>
#include <cstring>
using namespace std;

typedef
long long int lli;
const
int MAXN=12;
const
int MAXSTATE=300001;
int
N,M;
char
map[MAXN][MAXN];
int
sc,SC;
int
s_[MAXSTATE],S_[MAXSTATE];
lli f_[MAXSTATE],F_[MAXSTATE];
int
* s=s_;
int
* S=S_;
lli* f=f_;
lli* F=F_;
void
qsort(int l,int r)
{

int
i=l,j=r;
int
mid=S[(l+r)>>1];
while
(i<=j)
{

while
(S[i]<mid) i++;
while
(S[j]>mid) j--;
if
(i<=j)
{

int
SS;
lli SF;
SS=S[i],S[i]=S[j],S[j]=SS,SF=F[i],F[i]=F[j],F[j]=SF;
i++,j--;
}
}

if
(l<j) qsort(l,j);
if
(i<r) qsort(i,r);
}

lli min(lli a,lli b)
{

return
a<b?a:b;
}


int
run()
{

cin>>N>>M;
int
lasti=0,lastj=0;
for
(int i=1;i<=N;i++)
for
(int j=1;j<=M;j++)
{

cin>>map[i][j];
if
(map[i][j]=='o') lasti=i,lastj=j;
}

N++,M++;
lli answer=(~0u);

SC=0;
S[SC]=0;
F[SC]=0;
SC++;
for
(int i=0;i<N;i++)
{

for
(int j=0;j<M;j++)
{

int
* ss;
lli* sf;
ss=s,s=S,S=ss,sf=f,f=F,F=sf;
sc=SC,SC=0;

#define getp(state,p) (((state)>>((p)<<1))&3)
#define replace(state,p,n) (((state)&(~(3<<((p)<<1))))|n<<((p)<<1))
#define getl(state) getp(state,j)
#define getu(state) getp(state,j+1)
#define replacedr(state,d,r) replace(replace(state,j,d),j+1,r)
#define getcl(state,p,ns)\
do\
{\
ns=replacedr(state,0,0);\
int get=2;\
for (int i=p+2;i<=M;i++)\
{\
if (getp(ns,i)==1) get++;\
else if (getp(ns,i)==2) get--;\
if (get==1)\
{\
ns=replace(ns,i,1);\
break;\
}\
}\
}\
while (false)
#define getcr(state,p,ns)\
do\
{\
ns=replacedr(state,0,0);\
int get=2;\
for (int i=p-1;i>=0;i--)\
{\
if (getp(ns,i)==2) get++;\
else if (getp(ns,i)==1) get--;\
if (get==1)\
{\
ns=replace(ns,i,2);\
break;\
}\
}\
}\
while (false)
for (int si=0;si<sc;si++)
{

bool
out=true;
for
(int p=0;p<=j;p++)
if
(getp(s[si],p)) out=!out;
if
(map[i][j]=='o'&&out) continue;
if
(map[i][j]=='x'&&!out) continue;
int
l=getl(s[si]),u=getu(s[si]);
if
(l&&u)
{

int
ns;
if
(l==2&&u==1) ns=replacedr(s[si],0,0);
else if
(l==1&&u==1) getcl(s[si],j,ns);
else if
(l==2&&u==2) getcr(s[si],j,ns);
else

{

if
(((i>lasti)||(i==lasti&&j>=lastj))&&replacedr(s[si],0,0)==0) answer=min(answer,f[si]);
continue
;
}

S[SC]=ns;
F[SC]=f[si];
SC++;
}

else if
(l)
{

int
ns;
ns=replacedr(s[si],l,u);
S[SC]=ns;
F[SC]=f[si]+1;
SC++;
ns=replacedr(s[si],u,l);
S[SC]=ns;
F[SC]=f[si]+1;
SC++;
}

else if
(u)
{

int
ns;
ns=replacedr(s[si],l,u);
S[SC]=ns;
F[SC]=f[si]+1;
SC++;
ns=replacedr(s[si],u,l);
S[SC]=ns;
F[SC]=f[si]+1;
SC++;
}

else

{

int
ns;

//there can be a box without plug
ns=replacedr(s[si],0,0);
S[SC]=ns;
F[SC]=f[si];
SC++;

ns=replacedr(s[si],1,2);
S[SC]=ns;
F[SC]=f[si]+2;
SC++;
}
}
{

qsort(0,SC-1);
int
RSC=0;
int
i=0;
while
(i<SC)
{

int
j=i+1;
while
(j<SC&&S[i]==S[j]) F[i]=min(F[j],F[i]),j++;
S[RSC]=S[i];
F[RSC++]=F[i];
i=j;
}

SC=RSC;
}
}
{

int
RSC=0;
int
i=0;
while
(i<SC)
{

while
(i<SC&&getp(S[i],M)) i++;
if
(i<SC) S[RSC]=S[i]<<(1<<1),F[RSC++]=F[i++];
}

SC=RSC;
}
}

static
int casen;
cout<<"Case #"<<++casen<<": "<<int(answer)<<endl;
return
0;
}


int
main()
{

int
T;
for
(cin>>T;T;T--) run();
}

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注