P1074 靶形数独

来源:互联网 发布:mac版photoshop破解版 编辑:程序博客网 时间:2024/05/22 03:06
搜索能力菜的抠脚。
优化①:每次找出分支数最少的进行搜索。注意从前往后搜,因为从后往前搜要自爆的。
优化②:#pragma GCC optimize(“O2"),比绞尽脑汁卡常不知道高到哪里去了。
将没搜过的数放在一起,每次只查找那部分。然后发现自己的程序正好用了900多秒死233。
代码:
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cstdlib>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define ll long long#define db double#define mkp(x,y) make_pair(x,y)#define pii pair<int,int>#define X first#define Y secondint d[81],a[81],b[81],c[81],v[81],sum,ans,e[81];//d表示第i格填的数,a、b、c表示第i格属于第几行、列、九宫格,v表示第i格的权值,e为查找用的数组 bool ba[9][10],bb[9][10],bc[9][10];//表示第i行或列或九宫格是否填过j bool cmp(int x,int y){return d[x]>d[y];}void DFS(int k){    int i,j,mi=-1,my=-1,x,y;    rep(i,k,80)if(!d[x=e[i]]){        y=0;        rep(j,1,9)            y+=ba[a[x]][j]||bb[b[x]][j]||bc[c[x]][j];        if(y>my)my=y,mi=i;    }    if(mi<0){        ans=max(ans,sum);return;    }    swap(e[mi],e[k]);x=e[k];    rep(i,1,9)        if(!ba[a[x]][i]&&!bb[b[x]][i]&&!bc[c[x]][i]){            ba[a[x]][i]=bb[b[x]][i]=bc[c[x]][i]=1;            sum+=v[x]*(d[x]=i);DFS(k+1);            ba[a[x]][i]=bb[b[x]][i]=bc[c[x]][i]=0;            sum-=v[x]*i;d[x]=0;        }    swap(e[mi],e[k]);}int main(){    int i;    rep(i,0,80){        scanf("%d",&d[e[i]=i]);        a[i]=i/9;b[i]=i%9;c[i]=a[i]/3*3+b[i]/3;        v[i]=6+min(min(a[i],8-a[i]),min(b[i],8-b[i]));        if(d[i]){            if(ba[a[i]][d[i]]||bb[b[i]][d[i]]||bc[c[i]][d[i]]){                puts("-1");return 0;            }            ba[a[i]][d[i]]=bb[b[i]][d[i]]=bc[c[i]][d[i]]=1;            sum+=v[i]*d[i];        }    }    sort(e,e+81,cmp);    for(i=0;d[e[i]];++i);    ans=-1;DFS(i);printf("%d\n",ans);    return 0;}


原创粉丝点击