感觉我已经快不行惹 感觉自己有点弱竟然写了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; }