Paint on a Wall

时间:2021-12-25 18:54:06

Paint on a Wall

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4012

搜索+状态压缩

这题刚开始以为是dp(之前写过墙是一行的题,然而是在艾神讲完之后才调出来的= =),但是想不出来怎么搞,看到n<=8数据量这么小,应该搜索可以解,然后想都没想就上去写了IDA*,结果有段代码怎么都找不到bug,一直WA。

结束后,用bfs写了遍,每次转移数最多是(2n)^2,最差的情况是2n层,所以复杂度是(2n)^(4n),然而状态去重后,状态数最多为2^(2n)种,复杂度为[(2n)^2]*[2^(2n)],由于n很小,所以不会超时。然而如果用之前的IDA*,差不多会把深度小于deep的所有解空间遍历,一定会超时。

debug用了好几个小时,最后发现是

(lower&bit[other*n+i])>

写成了

(lower&bit[other*n+i])==

...不想说什么了...

代码如下:

 #include<cstdio>
#include<cstring>
#include<queue>
#define met(a,b) memset(a,b,sizeof(a))
#define mkp(state,deep) make_pair(state,deep)
#define X first
#define Y second
#define N 8
using namespace std;
typedef pair<int,int> P;
int T,n,ans,before,after;
char mp[][N+];
bool state[<<];
int bit[];
void init(){
for(int i=;i<=;++i)
bit[i]=(<<i);
}
void bfs(){
int finish=(<<(*n))-;
met(state,);
queue<P>q;
q.push(mkp(,));
state[]=;
while(!q.empty()){
P s=q.front();q.pop();
if(s.X==finish){
ans=s.Y;
return;
}
for(int c=;c<n;++c)
for(int r=;r<;++r)
if((s.X&bit[r*n+c])==){
char color=mp[r][c];
int other=(int)(!r);
int upper=s.X;
int lower=s.X;
int deep=s.Y;
for(int i=c;i<n;++i){
if((upper&bit[r*n+i])>&&mp[r][i]!=color)
upper^=bit[r*n+i];
else if((upper&bit[r*n+i])==&&mp[r][i]==color)
upper|=bit[r*n+i];
if((lower&bit[other*n+i])>&&mp[other][i]!=color)
lower^=bit[other*n+i];
else if((lower&bit[other*n+i])==&&mp[other][i]==color)
lower|=bit[other*n+i];
if(!state[upper]){
state[upper]=;
q.push(mkp(upper,deep+));
}
int temp;
if(r==)temp=(before&upper)|(after&lower);
else if(r==)temp=(after&upper)|(before&lower);
if(!state[temp]){
state[temp]=;
q.push(mkp(temp,deep+));
}
}
}
}
}
int main(void){
init();
scanf("%d",&T);
for(int t=;t<=T;++t){
scanf("%d\n",&n);
before=after=;
for(int i=;i<*n;++i){
if(i<n)before|=(<<i);
else after|=(<<i);
}
for(int i=;i<;++i)
scanf("%s",mp[i]);
bfs();
printf("Case #%d: ",t);
printf("%d\n",ans);
}
}