bzoj2515 Room

Description

Input

Output

折半搜索,用散列表记录从原点出发,用了S(状压表示)这几种边(令|S|*2-1<=n),到达(x,y)的最大面积。

#include<cstdio>
#include<cmath>
#include<algorithm>
int ps[301][8][2],pp[301],r[10],n,ed[10],st=0,ans;
#define cal(w,x,y,a,b,s) dfs(w,x+(a),y+(b),s+x*(b)-y*(a))
const int P=1844677;
int h[P][4],ht=0,ds[32];
void maxs(int&a,int b){if(a<b)a=b;}
void mins(int&a,int b){if(a>b)a=b;}
void ins(int st,int x,int y,int s){
    int X,w,st2=(1<<n)-1-st;
    if(ds[st2]==ht){
        X=(x+1024<<11|y+1024)<<6|st2;
        w=X%P;
        while(h[w][0]==ht){
            if(h[w][1]==X){
                maxs(ans,h[w][2]+s);
                break;
            }
            if((w+=1237)>=P)w-=P;
        }
    }else{
        ds[st]=ht;
        X=(x+1024<<11|y+1024)<<6|st;
        w=X%P;
        while(h[w][0]==ht){
            if(h[w][1]==X){
                maxs(h[w][2],s);
                return;
            }
            if((w+=1237)>=P)w-=P;
        }
        h[w][0]=ht;
        h[w][1]=X;
        h[w][2]=s;
    }
}
void dfs(int w,int x,int y,int s){
    if(w)ins(st,x,y,s);
    if(w<3)
    for(int i=0;i<n;++i)if(!ed[i]){
        ed[i]=1;
        st^=1<<i;
        int v=r[i];
        for(int j=0;j<pp[v];++j){
            int a=ps[v][j][0],b=ps[v][j][1];
            cal(w+1,x,y,a,b,s);
            cal(w+1,x,y,a,-b,s);
            cal(w+1,x,y,-a,b,s);
            cal(w+1,x,y,-a,-b,s);
            cal(w+1,x,y,b,a,s);
            cal(w+1,x,y,b,-a,s);
            cal(w+1,x,y,-b,a,s);
            cal(w+1,x,y,-b,-a,s);
        }
        st^=1<<i;
        ed[i]=0;
    }
}
int main(){
    for(int i=1;i<=300;++i){
        for(int j=0;j*j*2<=i*i;++j){
            int z=sqrt(i*i-j*j)+1e-10;
            if(j*j+z*z==i*i)ps[i][pp[i]][0]=j,ps[i][pp[i]++][1]=z;
        }
    }
    while(scanf("%d",&n)==1&&n){
        for(int i=0;i<n;++i)scanf("%d",r+i);
        ans=0;
        ++ht;
        dfs(0,0,0,0);
        if(!ans)puts("-1");
        else if(~ans&1)printf("%d
",ans>>1);
        else printf("%d.5
",ans>>1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/6212579.html