zoukankan      html  css  js  c++  java
  • [NOIP2009]靶形数独 深搜+枝杈优化

    这道题,又是一位玄学搜索......

    我是用的蜗牛序搜的(顾名思义,@,这么搜),我正着搜80然后一反转比原来快了几十倍........一下AC.......

    我的思路是这样的话我们可以从内到外或者从外到内搜索,这样的话我们就可以在一定程度上运用贪心,因为中间的价值大外面的价值小,我是作为一个从来没有玩过数独的人的思路...然而任何一个玩过数独的人都会先选可能状态少的优先搜索.......

    对于这题里的数据,可行方案很少因此摆在我们面前的不是减去不优的解而是减去不成立的解,然而对于不成立的解在我们真正意识到他不成立之前他也许是很优的,然而我们要提前预知是否是可行解基本不可行,那么我们就还真得爆搜了,然而怎样让我们的爆搜AC而不是TLE呢:我们搜索到的深度是一定的所以我们就要让他更晚“蓬松”,对于这样一个玄学的搜搜,我们这样的策略似乎是最可行且科学的了

    #include <cstdio>
    namespace Pre{
      inline void read(int &sum){
        register char ch=getchar();
        for(sum=0;ch<'0'||ch>'9';ch=getchar());
        for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=getchar());
      }
      inline int Max(int x,int y){
        return x>y?x:y;
      }
      inline int Abs(int x){
        return x<0?-x:x;
      }
      int bin[10],have[1025][10],pos[10][10],val[10][10];
      inline void Init(){
        bin[1]=1;
        for(int i=2;i<=9;i++)
          bin[i]=bin[i-1]<<1;
        int full=(1<<9)-1;
        for(int i=0;i<=full;i++)
          for(int j=9;j>0;j--)
            if((bin[j]&i)==0){
              have[i][++have[i][0]]=j;
            }
      }
      int ans;
    }
    namespace Handle{
      int line[10],column[10],big_lattice[10],key[10][10];
    }
    namespace point{
      struct Point{
        int x,y;
        inline friend Point operator + (Point a,Point b);
        inline void operator += (Point a){
          *this=(*this)+a;
        }
      }S,X,Z,Y,N,Queue[90];
      int len;
      inline Point operator + (Point a,Point b){
          return (Point){a.x+b.x,a.y+b.y};
      }
      inline void Init(){
        N.x=5,N.y=5;
        S.x=-1,S.y=0;
        X.x=1,X.y=0;
        Z.x=0,Z.y=-1;
        Y.x=0,Y.y=1;
      }
      inline Point To(){
        int Dis=Pre::Max(Pre::Abs(N.x-5),Pre::Abs(N.y-5));
        if(N.y==Dis+5&&N.x!=Dis+5)return X;
        if(N.x==Dis+5&&N.y!=5-Dis)return Z;
        if(N.x==5-Dis&&N.y!=5-Dis&&N.y!=5+Dis)return Y;
        if(N.y==5-Dis)return S;
      }
      inline int get_val(Point p){
        int Dis=Pre::Max(Pre::Abs(p.x-5),Pre::Abs(p.y-5));
        return 10-Dis;
      }
      inline int get_pos(Point p){
        return (p.x-1)/3*3+(p.y-1)/3+1;
      }
      inline void get_queue(){
        if(N.x==0)return;
        if(Handle::key[N.x][N.y]){
          N+=To();
          get_queue();
          return;
        }
        Queue[++len]=N;
        N+=To();
        get_queue();
      }
    }
    namespace Handle{
      inline void Insert(point::Point p,int Key){
        using Pre::bin;
        using Pre::pos;
        key[p.x][p.y]=Key;
        line[p.x]|=bin[Key];
        column[p.y]|=bin[Key];
        big_lattice[pos[p.x][p.y]]|=bin[Key];
      }
      inline void Delete(point::Point p){
        using Pre::bin;
        using Pre::pos;
        line[p.x]^=bin[key[p.x][p.y]];
        column[p.y]^=bin[key[p.x][p.y]];
        big_lattice[pos[p.x][p.y]]^=bin[key[p.x][p.y]];
        key[p.x][p.y]=0;
      }
    }
    namespace Main{
      void Init(){
        using namespace point;
        Pre::Init();
        point::Init();
        for(int i=1;i<=9;i++)
          for(int j=1;j<=9;j++)
            Pre::pos[i][j]=get_pos((Point){i,j}),
            Pre::val[i][j]=get_val((Point){i,j});
        for(int i=1,x;i<=9;i++)
          for(int j=1;j<=9;j++)
            Pre::read(x),Handle::Insert((Point){i,j},x),Pre::ans+=Pre::val[i][j]*x;
        get_queue();
        using namespace Handle;
        using Pre::pos;
        using Pre::val;
        using Pre::have;
      }
      void dfs(int Now,int Had){
        if(Now==0){
          Pre::ans=Pre::Max(Pre::ans,Had);
          return;
        }
        using namespace point;
        using namespace Handle;
        using Pre::pos;
        using Pre::val;
        using Pre::have;
        int Can=line[Queue[Now].x]|column[Queue[Now].y]|big_lattice[pos[Queue[Now].x][Queue[Now].y]];
        for(int i=1;i<=have[Can][0];i++){
          Handle::Insert(Queue[Now],have[Can][i]);
          dfs(Now-1,Had+have[Can][i]*val[Queue[Now].x][Queue[Now].y]);
          Handle::Delete(Queue[Now]);
        }
      }
      inline void Work(){
        int HAD=Pre::ans;
        dfs(point::len,HAD);
        if(point::len!=0&&HAD==Pre::ans)Pre::ans=-1;
      }
    }
    int main(){
      freopen("sudoku.in", "r", stdin);
      freopen("sudoku.out", "w", stdout);
      Main::Init();
      Main::Work();
      printf("%d",Pre::ans);
      return 0;
    }
  • 相关阅读:
    Java 第一章 初识Java
    Tomcat基础教程(三)
    Tomcat基础教程(二)
    Web Service相关工具的配置
    分布式版本控制系统Git的安装与使用
    个人项目小学四则运算 “软件”之初版
    结对项目四则运算 “软件”之升级版
    第一篇作业准备
    Linux常用命令入门文件、网络、系统及其他操作命令
    MySql5.7默认生成的密码无法正常登陆
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7327357.html
Copyright © 2011-2022 走看看