zoukankan      html  css  js  c++  java
  • 【noip2009】靶形数独

    题解:

    又是搜索- - 加状态压缩剪枝

    二进制记下每行 每列 每个九宫格用过的数是谁 枚举的时候可以O(1)判断冲突

    还有个很重要的剪枝 把可能使用数字最少的格子先搜索

    代码:

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <algorithm>
      4 using std::sort;
      5 const int N=82,n=9,val[10][10]={{0,0,0,0,0,0,0,0,0,0},
      6                                 {0,6,6,6,6,6,6,6,6,6},
      7                                 {0,6,7,7,7,7,7,7,7,6},
      8                                 {0,6,7,8,8,8,8,8,7,6},
      9                                 {0,6,7,8,9,9,9,8,7,6},
     10                                 {0,6,7,8,9,10,9,8,7,6},
     11                                 {0,6,7,8,9,9,9,8,7,6},
     12                                 {0,6,7,8,8,8,8,8,7,6},
     13                                 {0,6,7,7,7,7,7,7,7,6},
     14                                 {0,6,6,6,6,6,6,6,6,6}};
     15 struct info{
     16     int x,y,z;
     17     info(const int a=0,const int b=0,const int c=0):
     18         x(a),y(b),z(c){}
     19 }im[10][10],v[N];
     20 int map[10][10],xx[10],yy[10],zz[10],ans,maxans,rem;
     21 inline bool cmp(info a,info b){ return a.z>b.z || (a.z==b.z && a.x<b.x) || (a.z==b.z && a.x==b.x && a.y<b.y); }
     22 void print(int t){
     23     printf("%d",t);
     24     exit(0);
     25 }
     26 void makeim(){
     27     for (int i=1;i<=n;i++)
     28     for (int j=1;j<=n;j++){
     29         im[i][j].x=i;
     30         im[i][j].y=j;
     31         if (i<=3){
     32             if (j<=3) im[i][j].z=1;
     33             else if (j<=6) im[i][j].z=2;
     34             else im[i][j].z=3;
     35         }else if (i<=6){
     36             if (j<=3) im[i][j].z=4;
     37             else if (j<=6) im[i][j].z=5;
     38             else im[i][j].z=6;
     39         }else{
     40             if (j<=3) im[i][j].z=7;
     41             else if (j<=6) im[i][j].z=8;
     42             else im[i][j].z=9;
     43         }
     44     }
     45 }
     46 void makexyz(){
     47     for (int i=1;i<=n;i++)
     48     for (int j=1;j<=n;j++)
     49     if (map[i][j]){
     50         if ((xx[im[i][j].x]>>(map[i][j]-1))&1) print(-1);
     51         if ((yy[im[i][j].y]>>(map[i][j]-1))&1) print(-1);
     52         if ((zz[im[i][j].z]>>(map[i][j]-1))&1) print(-1);
     53         xx[im[i][j].x]|=1<<(map[i][j]-1);
     54         yy[im[i][j].y]|=1<<(map[i][j]-1);
     55         zz[im[i][j].z]|=1<<(map[i][j]-1);
     56     }
     57 }
     58 void makev(){
     59     for (int i=1;i<=n;i++)
     60     for (int j=1;j<=n;j++) v[(i-1)*n+j]=info(i,j,val[i][j]);
     61     sort(v+1,v+82,cmp);
     62 }
     63 bool check(int x,int y,int z){
     64     --z;
     65     if ((xx[im[x][y].x]>>z)&1) return 0;
     66     if ((yy[im[x][y].y]>>z)&1) return 0;
     67     if ((zz[im[x][y].z]>>z)&1) return 0;
     68     return 1;
     69 }
     70 void add(int x,int y,int z,int bo){
     71     --z;
     72     xx[im[x][y].x]+=bo*(1<<z);
     73     yy[im[x][y].y]+=bo*(1<<z);
     74     zz[im[x][y].z]+=bo*(1<<z);
     75 }
     76 int getsave(int t){
     77     int res=0;
     78     for (;t;t>>=1) res+=t&1;
     79     return res;
     80 }
     81 void search(){
     82     if (ans+rem*9<=maxans) return;
     83     int x=0,y,z=0;
     84     for (int i=1;i<=n;i++)
     85     for (int j=1;j<=n;j++)
     86     if (!map[i][j]){
     87         int save=getsave(xx[im[i][j].x]|yy[im[i][j].y]|zz[im[i][j].z]);
     88         if (save==9) return;
     89         if (save>z) z=save,x=i,y=j;
     90     }
     91     if (!x){
     92         if (maxans<ans) maxans=ans;
     93         return;
     94     }
     95     for (int i=9;i;i--)
     96     if (check(x,y,i)){
     97         rem-=i;
     98         ans+=i*val[x][y];
     99         add(x,y,i,1);
    100         map[x][y]=i;
    101         search();
    102         map[x][y]=0;
    103         add(x,y,i,-1);
    104         ans-=i*val[x][y];
    105         rem+=i;
    106     }
    107 }
    108 int main(){
    109     rem=45*9;
    110     for (int i=1;i<=n;i++)
    111     for (int j=1;j<=n;j++){
    112         scanf("%d",&map[i][j]);
    113         rem-=map[i][j];
    114         ans+=map[i][j]*val[i][j];
    115     }
    116     makeim();
    117     makexyz();
    118     makev();
    119     search();
    120     if (maxans) print(maxans);
    121     puts("-1");
    122 }
    View Code
  • 相关阅读:
    saltstack推送文件到节点
    Linux查看僵尸进程
    Linux批量对某个目录下特定文件进行修改内容
    Linux查看网络连接数
    Linux查看当前目录下哪个目录占用容量最多
    Linux查看inodes最多的目录
    Linux用命令过滤出ip地址
    mysql表字段的增删改操作
    Python安装模块超时
    sql 查询结果中加入空值列
  • 原文地址:https://www.cnblogs.com/g-word/p/3385174.html
Copyright © 2011-2022 走看看