dancing link X

今天上午看了看dlx算法,感觉非常巧妙。这里就用数独来举例子好了。

dancing link算法可以用来解决精确覆盖和重复覆盖问题。我暂时只会精确覆盖问题。我们用一个01矩阵来记录我们需要的东西。怎么说呢,就用数独来说吧。我们需要每一行每一列每一宫都只有一个1~9,所以说对于9*9=81个位置,我们得到了4个条件:

1,当前位置只能放一个数。

2,当前位置那一行只能放一种这个数。

3,当前位置那一列只能放一种这个数。

4,当前位置那一宫只能放这一个数。

所以我们关于这三个条件都有9*9种状态,然后81个位置每个位置可以放1~9,所以我们就得到了一个729*324的01矩阵。剩下的就是套板就行了。

dancing之所以快,是因为它的矩阵大小随着递归层数的增加,越来越小。并且它只记录了1的位置,大大缩短了时间。

接下来是数独的板,数独游戏弱爆了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 using namespace std;
  5 #define rp(x,y) (x)*9+y+81
  6 #define cp(x,y) (x)*9+y+162
  7 #define pp(x,y) (x)*9+y+243
  8 const int N = 60003;
  9 const int INF = 0x7fffffff;
 10 int u[N],d[N],L[N],R[N];
 11 int X[N],C[N],s[1003],h[1003],tot,id,ans[103];
 12 bool mark[1003];
 13 struct data {
 14     int pos,val;
 15 }a[1003],q[103];
 16 inline void del(int c) {
 17     L[R[c]] = L[c] ; R[L[c]] = R[c];
 18     for(int i = d[c] ; i != c ; i = d[i])
 19         for(int j = R[i] ; j != i ; j = R[j])
 20             d[u[j]] = d[j] , u[d[j]] = u[j] , s[C[j]]--;
 21 }
 22 inline void add(int c) {    
 23     L[R[c]] = R[L[c]] = c;
 24     for(int i = u[c] ; i != c ; i = u[i])
 25         for(int j = L[i] ; j != i ; j = L[j])
 26             d[u[j]] = u[d[j]] = j , s[C[j]]++;
 27 }
 28 inline void link(int r,int c) {
 29     s[c]++ ; C[++tot] = c ; X[tot] = r;
 30     u[tot] = c ; d[tot] = d[c];
 31     u[d[tot]] = tot ; d[u[tot]] = tot;
 32     if(h[r]==-1) {
 33         h[r] = L[tot] = R[tot] = tot;
 34     } else {
 35         L[tot] = h[r] ; R[tot] = R[h[r]];
 36         L[R[tot]] = tot ; R[L[tot]] = tot;
 37     }
 38 }
 39 inline bool dance(int k) {
 40     if(R[0]==0) {
 41         for(int i = 1 ; i <= 81 ; ++i) ans[q[i].pos] = q[i].val;
 42         for(int i = 1 ; i <= 81 ; ++i) printf("%d",ans[i]);
 43         printf("\n");
 44         return 1;
 45     }
 46     int temp = INF , c = R[0];
 47     for(int i = R[0] ; i ; i = R[i])
 48         if(s[i] < temp) temp = s[i] , c = i;
 49     del(c);
 50     for(int i = d[c] ; i != c ; i = d[i]) {
 51         q[k+1] = a[X[i]];
 52         for(int j = R[i] ; j != i ; j = R[j]) del(C[j]);
 53         if(dance(k+1)) return 1;
 54         for(int j = L[i] ; j != i ; j = L[j]) add(C[j]);
 55     }
 56     add(c);
 57     return 0;
 58 }
 59 char ch[203];
 60 int main() {
 61     while(scanf("%s",ch+1)) {
 62         if(ch[1]=='e') return 0;
 63         id = tot = 0;
 64         memset(h,-1,sizeof(h));
 65         memset(mark,0,sizeof(mark));
 66         for(int i = 0 ; i <= 4*81 ; ++i) {
 67             R[i] = i + 1 ; L[i+1] = i;
 68             u[i] = d[i] = i;
 69             s[i] = 0;
 70         }
 71         L[0] = 4*81 ; R[4*81] = 0 ; tot = 4*81;
 72         for(int i = 0 ; i < 9 ; ++i) 
 73             for(int j = 0 ; j < 9 ; ++j)
 74                 if(ch[i*9+j+1]!='.') {
 75                     int t = ch[i*9+j+1]-'0' , p = i/3*3+j/3;
 76                     mark[rp(i,t)] = mark[cp(j,t)] = mark[pp(p,t)] = 1;
 77                 }
 78         for(int i = 0 ; i < 9 ; ++i)
 79             for(int j = 0 ; j < 9 ; ++j) {
 80                 int t = ch[i*9+j+1]!='.'?ch[i*9+j+1]-'0':0;
 81                 int p = i/3*3+j/3;
 82                 if(t) {
 83                     id++ ; a[id].pos = i*9+j+1 ; a[id].val = t;
 84                     link(id,i*9+j+1);
 85                     link(id,rp(i,t));
 86                     link(id,cp(j,t));
 87                     link(id,pp(p,t));
 88                 } else {
 89                     for(int k = 1 ; k <= 9 ; ++k) {
 90                         if(!mark[rp(i,k)]&&!mark[cp(j,k)]&&!mark[pp(p,k)]) {
 91                             id++ ; a[id].pos = i*9+j+1 ; a[id].val = k;
 92                             link(id,i*9+j+1);
 93                             link(id,rp(i,k));
 94                             link(id,cp(j,k));
 95                             link(id,pp(p,k));
 96                         }
 97                     }
 98                 }
 99             }
100         dance(0);
101     }
102 }
View Code

 

转载于:https://www.cnblogs.com/registerzxr/p/5142218.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dancing Links 算法是用于解决精确覆盖问题的算法,俄罗斯方块覆盖问题可以被转化为精确覆盖问题,因此可以使用 Dancing Links 算法求解。下面是使用 Matlab 实现 Dancing Links 算法解决俄罗斯方块覆盖问题的代码: ```matlab function [sol, num_solutions] = tetris_dlx(m, n, blocks) % m: 棋盘行数 % n: 棋盘列数 % blocks: 方块形状,每个方块用一个矩阵表示(0表示空,1表示方块) max_nodes = m * n * numel(blocks); % 初始化 Dancing Links 数据结构 dl = DancingLinks(max_nodes); % 构建 Dancing Links 矩阵 for i = 1:m for j = 1:n for k = 1:numel(blocks) block = blocks{k}; if i + size(block, 1) - 1 > m || j + size(block, 2) - 1 > n continue; end % 将方块转换为约束条件 constraint = zeros(m, n); constraint(i:i+size(block,1)-1, j:j+size(block,2)-1) = block; % 将约束条件插入 Dancing Links 矩阵 columns = (i-1)*n + j + (0:numel(constraint)-1)*m*n; dl.insert_constraint(columns, constraint(:)); end end end % 解决 Dancing Links 矩阵,得到所有解 solutions = dl.solve(); % 将解转换为棋盘布局 num_solutions = size(solutions, 2); sol = cell(num_solutions, 1); for i = 1:num_solutions sol{i} = zeros(m, n); for j = solutions(:, i)' [row, col, k] = ind2sub([m, n, numel(blocks)], j); block = blocks{k}; sol{i}(row:row+size(block,1)-1, col:col+size(block,2)-1) = block; end end end ``` 这个函数接受三个参数:棋盘行数 `m`,棋盘列数 `n`,和方块形状 `blocks`。`blocks` 是一个包含所有方块形状的矩阵数组,每个矩阵表示一个方块,其中 0 表示空,1 表示方块。函数返回两个值:`sol` 是包含所有解的单元格数组,每个单元格表示一个解的棋盘布局;`num_solutions` 是找到的解的数量。 下面是一个使用示例: ```matlab % 定义方块形状 block1 = [1 1; 1 1]; block2 = [1 1 1; 0 1 0]; block3 = [1 1 1; 0 1 1]; block4 = [1 1 0; 0 1 1]; blocks = {block1, block2, block3, block4}; % 解决俄罗斯方块覆盖问题 sol = tetris_dlx(4, 4, blocks); for i = 1:numel(sol) disp(sol{i}); end ``` 这个例子解决了一个 4x4 的俄罗斯方块覆盖问题,使用了四种不同的方块形状。程序输出所有解的棋盘布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值