用二进制优化常数卡过Pku3074 Sudoku

原创 2013年12月03日 14:05:43

这道题看起来用暴力搜索似乎不可能过,但是因为二进制的运行速度实在是太快了。我们可以用二进制运算来代替布尔型的for循环枚举。这样,我们便可以节省大量时间。

我是用了l[i],h[i],kuai[i]分别代表第i列,第i行,第i块的状态,0代表未出现过,1代表已出现。

我还每次找可以填的数字最少的格子进行搜索,便把这题卡过去了。

接下来上代码:

const
 w:array[0..8,0..8]of longint=((0,0,0,1,1,1,2,2,2),
                              (0,0,0,1,1,1,2,2,2),
                              (0,0,0,1,1,1,2,2,2),
                              (3,3,3,4,4,4,5,5,5),
                              (3,3,3,4,4,4,5,5,5),
                              (3,3,3,4,4,4,5,5,5),
                              (6,6,6,7,7,7,8,8,8),
                              (6,6,6,7,7,7,8,8,8),
                              (6,6,6,7,7,7,8,8,8));
var
bb,aa:array[0..512]of longint;
a:array[0..8,0..8]of longint;
h,l,kui:array[0..8]of longint;
now,minn,x,y,ans,n,m,i,j,k:longint;
s:string;

procedure dfs(x,y:longint);
var
ii,jj,xx,yy,minn,i,j,k:longint;
begin
if (a[x,y]<>-1) then
  begin
    ans:=1;
    exit;
  end;
i:=1;
j:=l[y] or h[x] or kui[w[x,y]];
if j=511 then
  exit;
while i<512 do
begin
     if j or i<>j then
             begin
               l[y]:=l[y] or i;
               h[x]:=h[x] or i;
               kui[w[x,y]]:=kui[w[x,y]]or i;
               a[x,y]:=bb[i];
               minn:=16;
               xx:=0;yy:=0;
               ii:=0;
               while ii<=8 do
                begin
                 for jj:=0 to 8 do
                   if a[ii,jj]=-1 then
                    begin
                      k:=l[jj] or h[ii] or kui[w[ii,jj]];
                      if aa[k]<minn then
                        begin
                          minn:=aa[k];
                          xx:=ii; yy:=jj;
                        end;
                      if minn=1 then
                         begin
                           ii:=9;
                           break;
                         end;
                    end;
                    inc(ii);
                 end;
               dfs(xx,yy);
               if ans<>0 then
                 exit;
               l[y]:=l[y] and (not i);
               h[x]:=h[x] and (not i);
               kui[w[x,y]]:=kui[w[x,y]] and (not i);
             end;
           i:=i<<1;
end;
a[x,y]:=-1;
end;

begin
bb[1]:=0; bb[2]:=1; bb[4]:=2; bb[8]:=3; bb[16]:=4;
bb[32]:=5; bb[64]:=6; bb[128]:=7;bb[256]:=8;
for k:=0 to 512 do
  begin
          now:=0;
          if k or 1<>k then
            inc(now);
          if k or 2<>k then
            inc(now);
          if k or 4<>k then
            inc(now);
          if k or 8<>k then
            inc(now);
          if k or 16<>k then
            inc(now);
          if k or 32<>k then
            inc(now);
          if k or 64<>k then
            inc(now);
          if k or 128<>k then
            inc(now);
          if k or 256<>k then
            inc(now);
          aa[k]:=now;
  end;
while not eof do
  begin
    fillchar(h,sizeof(h),0);
    fillchar(l,sizeof(l),0);
    fillchar(kui,sizeof(kui),0);
    fillchar(a,sizeof(a),$ff);
    readln(s);    ans:=0;
    if s[1]='e' then
      break;
    for i:=0 to 80 do
      if  s[i+1]<>'.' then
        begin
          j:=ord(s[i+1])-ord('1');
          a[i div 9,i mod 9]:=j;
          h[i div 9]:=h[i div 9] or (1<<j);
          l[i mod 9]:=l[i mod 9] or (1<<j);
          kui[w[i div 9,i mod 9]]:=kui[w[i div 9,i mod 9]] or(1<<j);
        end;
    minn:=16;
    i:=0;
    while i<=8 do
      begin
      for j:=0 to 8 do
        if a[i,j]=-1 then
        begin
          k:=l[j] or h[i] or kui[w[i,j]];
          if aa[k]<minn then
            begin
              minn:=aa[k];
              x:=i; y:=j;
            end;
          if minn=1 then
            begin
              i:=9;
              break;
            end;
        end;
        inc(i);
      end;
    dfs(x,y);
    for i:=0 to 8 do
      begin
        for j:=0 to 8 do
          write(a[i,j]+1);
      end;
    writeln;
  end;
end.

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj 3074 Sudoku

坑爹的数独呀!又是搜索,又是剪枝~~~ 代码如下: #include #include #include const int MAX_COLOUMN=81+9*9+9*9+9*9+2; const...

POJ 3074 Sudoku(数据结构,DLX)

http://poj.org/problem?id=3074

【poj3074】【DLX】sudoku

就是数独 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9617 Accep...

POJ 3074 Sudoku

Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × ...

POJ 3074 Sudoku 舞蹈链

#include #include #include #include #include #include #include #include #include #include ...

poj 3074 Sudoku(Dancing Links)

Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8152   Accepte...

poj 3074 Sudoku dlx解数独

分析: dlx是从数据结构角度优化01矩阵精确覆盖和重复覆盖的数据结构,它用十字链表只存贮矩阵中的非0元,而01矩阵精确覆盖dfs过程中矩阵会越来越稀疏而且每次恢复现场会浪费大量时间,dlx恰好能解...

poj3074 Sudoku--舞蹈链数独

原题链接:http://poj.org/problem?id=3074 题意:给定一个9*9的数独,求解。 #define _CRT_SECURE_NO_DEPRECATE #includ...

PKU 3074

DLX数独建图:一共9*9*9 = 729行,9*9*4 = 324列。第i行表示数独的i/81行i/9%9列放置数字i%9。324列分成4个部分,每个部分81列,分别限制每个格子只能放一个数字、每行...

dancing links 算法学习小记 Poj 3074 Sudoku (数独)

论文:dancing links完整中文翻译版_百度文库 学习链接:dancing links 算法 解 Sudoku - liujiyong7的专栏 - 博客频道 - CSDN.NET 代码...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)