[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;
}
时间: 2024-10-22 11:45:15

[NOIP2009]靶形数独 深搜+枝杈优化的相关文章

[NOIP2009] 靶形数独

[NOIP2009] 靶形数独 传送门 题目 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) .在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1到 9 的

[NOIP2009]靶形数独 题解

407. [NOIP2009] 靶形数独 ★★   输入文件:sudoku.in   输出文件:sudoku.out   简单对比时间限制:5 s   内存限制:128 MB [问题描述] 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格

[NOIP2009] 靶形数独(搜索+剪枝)

题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格 高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字.每个数字在每个

NOIP2009 靶形数独(搜索)

以前做过一道hdu类似的数独题,那道题我没有加什么优化就过了,然后这道题不加优化可以得50~80分,要上80分就必须要优化 可以用位运算保存每一行每一列每个九宫格内已经使用的数,例如userow[i] = 011101111表示第i行还有1,5两个数字没有使用,那么我们枚举每个未知的格子(i,j)时,他不能填的数就是userow[i]|usecol[j]|usebox[i/3*3+j/3] ,其实这样做也不能优化什么时间,下面才是最NB的优化 在输入的时候我们可以统计每一行已知的数,于是我们能够

(hdu)5547 Sudoku (4*4方格的 数独 深搜)

Problem Description Yi Sima was one of the best counselors of Cao Cao. He likes to play a funny game himself. It looks like the modern Sudoku, but smaller. Actually, Yi Sima was playing it different. First of all, he tried to generate a 4×4 board wit

【NOIP2009】靶形数独 DLX(Dancing Links)

[NOIP2009]靶形数独 T4 Time Limit: 2 Sec  Memory Limit: 128 MB Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z 博士请教,Z 博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在

P1074 靶形数独

P1074 靶形数独正着搜80分,完全倒置95分,完全倒置后左右再倒置,就会A掉,到时候脑洞要大一些. 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<set> 8 #include<map> 9 #incl

靶形数独【贪心+深搜】

问题描述小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,Z博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在9格宽×9格高的大九宫格中有9个3格宽×3格高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入1到9的数字.每个数字在每个小九宫格内不能重复出现,每个数字在每行

【NOIP2009】靶形数独

P1687 - [NOIP2009]靶形数独 Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的"靶形数独" ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的) .在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理