poj3074 & 3076 数独 Dancing Links

今天早上又在poj看到一个数独题,粘了以前的爆搜T了,就翻出了以前写的4阶数独改了改

DancingLinks就是快


3074  三阶版

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <utility>
#include <map>
#define pb push_back
#define mp make_pair
#define N 1025
#define M 20005
using namespace std;

int U[M] , D[M] , L[M] , R[M], col[M] , row[M];
int cnt , p[N] , s[N] , T;
char t[101];
vector<int> ans;

int V(int x , int y)
{
  return ((x / 3) * 3) + (y / 3);
}

#define FOR(i,A,s) for(int i = A[s]; i != s ; i = A[i])

void remove(int c)
{
  L[R[c]] = L[c] , R[L[c]] = R[c];
  FOR(i,D,c) FOR(j,R,i)
    U[D[j]] = U[j] , D[U[j]] = D[j] , -- s[col[j]];
}
void resume(int c)
{
  FOR(i,U,c) FOR(j,L,i)
    U[D[j]] = D[U[j]] = j , ++ s[col[j]];
  L[R[c]] = R[L[c]] = c;
}

bool dfs(int d)
{
  if (R[0] == 0)
    return 1;
  int c = R[0];
  FOR(i,R,0) if (s[i] < s[c]) c = i;

  remove(c);
  FOR(i,D,c)
  {
    ans.pb(row[i]);
    FOR(j,R,i) remove(col[j]);
    if (dfs(d + 1)) return 1;
    FOR(j,L,i) resume(col[j]);
    ans.pop_back();
  }
  resume(c);
  return 0;
}

void initmatrix()
{
  int i , j , x , y , z , v , opt[4];
  cnt = 325;
  for (i = 0 ; i < cnt ; ++ i)
    L[i] = i - 1 , R[i] = i + 1 , p[i] = i , s[i] = 0;
  L[0] = 324 , R[324] = 0;
  for (i = 0 ; i < 729 ; ++ i)
  {
    x = i / 81 , y = (i / 9) % 9 , z = i % 9; // (x , y) : A + 'z'
    v = V(x , y);
    opt[0] = 9 * x + y + 1;
    opt[1] = 9 * x + z + 81 + 1;
    opt[2] = 9 * y + z + 162 + 1;
    opt[3] = 9 * v + z + 243 + 1;
    for (j = 0 ; j < 4 ; j ++)
    {
      L[cnt + j] = cnt + j - 1 , R[cnt + j] = cnt + j + 1;
      D[p[opt[j]]] = cnt + j , U[cnt + j] = p[opt[j]] , p[opt[j]] = cnt + j;
      col[cnt + j] = opt[j] , row[cnt + j] = i , ++ s[opt[j]];
    }
    L[cnt] = cnt + 3 , R[cnt + 3] = cnt;
    cnt += 4;
  }
  for (i = 0 ; i < 325 ;i ++)
    D[p[i]] = i , U[i] = p[i];
}

bool work()
{
  int i , j , x , y , z , v;
  ans.clear();
  char str[12][12] = {};
  if (++ T != 1) puts("");
  initmatrix();
  for (i = 0 ; i < 9 ; ++ i)
    for (j = 0 ; j < 9 ; ++ j)
      str[i][j] = t[i * 9 + j];
  for (x = 0 ; x < 9 ; ++ x)
    for (y = 0 ; y < 9 ; ++ y)
      if (str[x][y] != '.')
      {
        z = str[x][y] - '1';
        v = V(x , y);
        remove(9 * x + y + 1) , remove(9 * x + z + 81 + 1) , remove(9 * y + z + 162 + 1) , remove(9 * v + z + 243 + 1);
      }
  dfs(0);
  for (i = ans.size() - 1 ; i >= 0 ; -- i)
    x = ans[i] , str[x / 81][(x / 9) % 9] = '1' + (x % 9);
  for (i = 0 ; i < 9 ; ++ i)
    printf("%s",str[i]);
  return 0;
}

int main()
{
  while(scanf("%s" , t) , *t != 'e') work();
  return 0;
}

3076 4阶版

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <utility>
#include <map>
#define pb push_back
#define mp make_pair
#define N 1025
#define M 20005
using namespace std;

int U[M] , D[M] , L[M] , R[M], col[M] , row[M];
int cnt , p[N] , s[N] , T;

vector<int> ans;

int V(int x , int y)
{
  return ((x >> 2) << 2) + (y >> 2);
}

#define FOR(i,A,s) for(int i = A[s]; i != s ; i = A[i])

void remove(int c)
{
  L[R[c]] = L[c] , R[L[c]] = R[c];
  FOR(i,D,c) FOR(j,R,i)
    U[D[j]] = U[j] , D[U[j]] = D[j] , -- s[col[j]];
}
void resume(int c)
{
  FOR(i,U,c) FOR(j,L,i)
    U[D[j]] = D[U[j]] = j , ++ s[col[j]];
  L[R[c]] = R[L[c]] = c;
}

bool dfs(int d)
{
  if (R[0] == 0)
    return 1;
  int c = R[0];
  FOR(i,R,0) if (s[i] < s[c]) c = i;

  remove(c);
  FOR(i,D,c)
  {
    ans.pb(row[i]);
    FOR(j,R,i) remove(col[j]);
    if (dfs(d + 1)) return 1;
    FOR(j,L,i) resume(col[j]);
    ans.pop_back();
  }
  resume(c);
  return 0;
}

void initmatrix()
{
  int i , j , x , y , z , v , opt[4];
  cnt = 1025;
  for (i = 0 ; i < 1025 ; ++ i)
    L[i] = i - 1 , R[i] = i + 1 , p[i] = i , s[i] = 0;
  L[0] = 1024 , R[1024] = 0;
  for (i = 0 ; i < 4096 ; ++ i)
  {
    x = i >> 8 , y = (i >> 4) & 0xf , z = i & 0xf; // (x , y) : A + 'z'
    v = V(x , y);
    opt[0] = 16 * x + y + 1;
    opt[1] = 16 * x + z + 256 + 1;
    opt[2] = 16 * y + z + 512 + 1;
    opt[3] = 16 * v + z + 768 + 1;
    for (j = 0 ; j < 4 ; j ++)
    {
      L[cnt + j] = cnt + j - 1 , R[cnt + j] = cnt + j + 1;
      D[p[opt[j]]] = cnt + j , U[cnt + j] = p[opt[j]] , p[opt[j]] = cnt + j;
      col[cnt + j] = opt[j] , row[cnt + j] = i , ++ s[opt[j]];
    }
    L[cnt] = cnt + 3 , R[cnt + 3] = cnt;
    cnt += 4;
  }
  for (i = 0 ; i < 1025 ;i ++)
    D[p[i]] = i , U[i] = p[i];
}

bool work()
{
  int i , j , x , y , z , v;
  ans.clear();
  char str[16][20];
  if (!~scanf("%s\n",str[0]))
    return 1;
  if (++ T != 1) puts("");
  initmatrix();
  for (i = 1 ; i < 16 ; ++ i)
    scanf("%s\n",str[i]);
  for (x = 0 ; x < 16 ; ++ x)
    for (y = 0 ; y < 16 ; ++ y)
      if (str[x][y] != '-')
      {
        z = str[x][y] - 'A';
        v = V(x , y);
        remove(16 * x + y + 1) , remove(16 * x + z + 256 + 1) , remove(16 * y + z + 512 + 1) , remove(16 * v + z + 768 + 1);
      }
  dfs(0);
  for (i = ans.size() - 1 ; i >= 0 ; -- i)
    x = ans[i] , str[x >> 8][(x >> 4) & 0xf] = 'A' + (x & 0xf);
  for (i = 0 ; i < 16 ; ++ i)
    printf("%s\n",str[i]);
  return 0;
}

int main()
{
  while(1) if(work()) break;
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值