感觉我已经快不行惹 感觉自己有点弱竟然写了2h= =
开始并没发现可以状压【英语渣没看懂题目,后来偷窥了一下大神博客,发现空的格子不超过10个,于是我们考虑状压,三进制分别表示空格,0,1,四进制最开始以为开不下= =
然后我们传递还有哪些空格还没被选过,二进制高效处理,新姿势:用pos=log(k+0.5)/log(2.0)或者pos=log(k-0.5)/log(2.0)+1来获取是哪一位
AB剪枝,在搜索某个节点的子树过程中,发现当前子树怎样也无法得到比“当前已搜索过的子树得到的结果”(alpha或者beta)更优的结果时return那个值就行,切记不可把值传给f[now]。
时间复杂度O(n*n*2^m)剪枝或者状压后就可以过惹
Problem: 3317 User: BPM136
Memory: 2768K Time: 172MS
Language: G++ Result: Accepted
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define LL long long
#define get(i,j) (i*n+j)
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 10
#define MIN -10000
#define MAX 10000
struct point
{
int x,y;
point()
{
x=y=0;
}
point(int x_,int y_)
{
x=x_;y=y_;
}
}d[100],ans;
int map[N][N];
int n,nd=0,anss;
int po[21];
int f[1<<20];
char s[100];
bitset<100>v;
int pri[4][2];
int dfs(int x,int y,int k)
{
if(x<0||y<0||x>=n||y>=n)return 0;
if(v[get(x,y)])return 0;
if(map[x][y]!=k)return 0;
v[get(x,y)]=1;
int t=1;
fo(i,0,3)
t+=dfs(x+pri[i][0],y+pri[i][1],k);
return t;
}
int getvalue(int now)
{
v.reset();int st=now;
fo(i,0,nd-1)
{
int t=st%3;st/=3;
map[d[i].x][d[i].y]=t;
}
int ans0=0,ans1=0;
fo(i,0,n-1)
{
fo(j,0,n-1)
{
// cout<<get(i,j)<<' '<<i<<' '<<j<<' '<<map[i][j]<<endl;
if(v[get(i,j)]==0)
{
// cout<<1222<<endl;
int t=dfs(i,j,map[i][j]);
// cout<<"suess"<<endl;
if(map[i][j]==1)
{
ans0=max(ans0,t);
}else
{
ans1=max(ans1,t);
}
}
}
}
fo(i,0,nd-1)
{
map[d[i].x][d[i].y]=0;
}
return ans0-ans1;
}
int minimax(int status,int dep,int now,int beta);
int maxmini(int status,int dep,int now,int alpha);
int minimax(int status,int dep,int now,int beta)
{
if(status==0)return getvalue(now);
if(f[now]!=MIN)return f[now];
int mi=MAX;
int st=status;
while(st)
{
int k=st&(-st);
int pos=log(k+0.5)/log(2.0);
int t=maxmini(status-k,dep+1,now+po[pos]*2,mi);
mi=min(mi,t);
if(mi<=beta)return mi;
st-=k;
}
return f[now]=mi;
}
int maxmini(int status,int dep,int now,int alpha)
{
if(status==0)return getvalue(now);
if(f[now]!=MIN) return f[now];
int ma=MIN;
int st=status;
while(st)
{
int k=st&(-st);
int pos=log(k+0.5)/log(2.0);
int t=minimax(status-k,dep+1,now+po[pos],ma);
ma=max(ma,t);
if(ma>=alpha)return ma;
if(status==(1<<nd)-1)
{
if(ma>anss)
{
ans=d[pos];
anss=ma;
}
}
st-=k;
}
return f[now]=ma;
}
void init()
{
int c1=0,c0=0;nd=0;
memset(map,0,sizeof(map));
fo(i,0,n-1)
{
scanf("%s",s);
fo(j,0,n-1)
{
if(s[j]=='.')
{
map[i][j]=0;
d[nd++]=point(i,j);
}else
if(s[j]=='0')
{
map[i][j]=1,c0++;
}else
if(s[j]=='1')
{
map[i][j]=2,c1++;
}
}
}
if(c0>c1)
{
fo(i,0,n-1)
{
fo(j,0,n-1)
if(map[i][j])
{
map[i][j]^=3;
}
}
}
fo(i,0,1<<20-1)f[i]=MIN;
ans=point(0,0);anss=MIN;
}
void check()
{
fo(i,0,n-1)
{
fo(j,0,n-1)
cout<<map[i][j];
cout<<endl;
}cout<<endl;
}
int main()
{
int tt=0;
fo(i,-1,1)
fo(j,-1,1)
if(abs(i-j)==1)
{
pri[tt][0]=i,pri[tt++][1]=j;
}
po[0]=1;nd=0;
fo(i,1,10)po[i]=po[i-1]*3;
while(scanf("%d",&n)!=EOF&&n)
{
init();
// check();
maxmini((1<<nd)-1,0,0,MAX);
printf("(%d,%d) %d\n",ans.x,ans.y,anss);
fo(i,0,nd-1)d[i]=point(0,0);nd=0;
}
return 0;
}