• POJ 1084 Square Destroyer (重复覆盖,DLX)


    题目:

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

    题意:

    给你一个n*n(n<=5)的完全由火柴棍组成的正方形,已经去掉了一些火柴棍,问最少去掉多少根火柴棍使得所有1*1、2*2......n*n的正方形均被破坏掉?

    方法:

    转换为重复覆盖问题,用DLX直接解决

    1、精确覆盖与重复覆盖:《DLX在搜索中的应用》

    http://bbs.whu.edu.cn/wForum/elite.php?file=%2Fgroups%2FGROUP_3%2FACM_ICPC%2Fnx08%2FD.08010000%2FM.1215524645.R0&ap=563

    2、转换方法:矩阵的一行代表一根火柴棍,矩阵的一列代表一个正方形,即转换位矩阵重复覆盖问题

    3、处理去掉的火柴棍:

    (a)先计算不去掉火柴棍的矩阵,给火柴棍和矩阵编上号手推一下就发现规律了,我的编号和建立矩阵的方法:

     1 void calmtx()
     2 {
     3     row = 2 * n * (n + 1);
     4     col = 0;
     5     for (int i = 1; i <= n; i++)
     6         col += i * i;
     7 
     8     int cnt = 1;
     9     for (int si = 1; si <= n; si++)
    10     {
    11         for (int i = 1; i <= n - si + 1; i++)
    12         {
    13             for (int j = 1; j <= n - si + 1; j++)
    14             {
    15                 for (int k = 0; k < si; k++)
    16                 {
    17                     mtx[(i - 1) * (2 * n + 1) + j + k][cnt] = 1;
    18                     mtx[(i - 1 + si) * (2 * n + 1) + j + k][cnt] = 1;
    19                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1)][cnt] = 1;
    20                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1) + si][cnt] = 1;
    21                 }
    22                 cnt++;
    23             }
    24         }
    25     }
    26 }

    (b)去掉火柴棍:对去掉的火柴棍对应的正方形加标记并在DLX里面标记它们已经访问过,然后在添加link时忽略这些标记过的正方形

     1 void build()
     2 {
     3     calmtx();
     4 
     5     dlx.initL(col);
     6     for (int i = 0; i < vec.size(); i++)
     7     {
     8         int x = vec[i];
     9         for (int j = 1; j <= col; j++)
    10             if (mtx[x][j] && !vis[j])
    11             {
    12                 vis[j] = 1;
    13                 dlx.R[dlx.L[j]] = dlx.R[j];
    14                 dlx.L[dlx.R[j]] = dlx.L[j];
    15                 dlx.R[j] = dlx.L[j] = 0;
    16             }
    17     }
    18     for (int i = 1; i <= row; i++)
    19     {
    20         for (int j = 1; j <= col; j++)
    21         {
    22             if (mtx[i][j] && !vis[j])
    23                 dlx.Link(i, j);
    24         }
    25     }
    26 }

    代码:

      1 /********************************************
      2 *ACM Solutions
      3 *
      4 *@Title: POJ 1084 Square Destroyer
      5 *@Version: 1.0
      6 *@Time: 2014-09-29
      7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
      8 *
      9 *@Author: xysmlx(Lingxiao Ma)
     10 *@Blog: http://www.cnblogs.com/xysmlx
     11 *@EMail: xysmlx@163.com
     12 *
     13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
     14 ********************************************/
     15 // #pragma comment(linker, "/STACK:102400000,102400000")
     16 #include <cstdio>
     17 #include <iostream>
     18 #include <cstring>
     19 #include <string>
     20 #include <cmath>
     21 #include <set>
     22 #include <list>
     23 #include <map>
     24 #include <iterator>
     25 #include <cstdlib>
     26 #include <vector>
     27 #include <queue>
     28 #include <stack>
     29 #include <algorithm>
     30 #include <functional>
     31 using namespace std;
     32 typedef long long LL;
     33 #define pb push_back
     34 #define ROUND(x) round(x)
     35 #define FLOOR(x) floor(x)
     36 #define CEIL(x) ceil(x)
     37 const int maxn = 110;
     38 const int maxm = 0;
     39 const int inf = 0x3f3f3f3f;
     40 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     41 const double INF = 1e30;
     42 const double eps = 1e-6;
     43 const int P[4] = {0, 0, -1, 1};
     44 const int Q[4] = {1, -1, 0, 0};
     45 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     46 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     47 
     48 /*
     49 重复覆盖:DLX
     50 输入:Link()
     51 输出:ans, bool Dance(int k)
     52 */
     53 const int maxnode = 360000;
     54 const int maxc = 500;
     55 const int maxr = 500;
     56 // const int inf = 0x3f3f3f3f;
     57 struct DLX
     58 {
     59     int L[maxnode], R[maxnode], D[maxnode], U[maxnode], C[maxnode];
     60     int S[maxc], H[maxr], size;
     61     int ans;
     62     ///不需要S域
     63     void Link(int r, int c)
     64     {
     65         S[c]++; C[size] = c;
     66         U[size] = U[c]; D[U[c]] = size;
     67         D[size] = c; U[c] = size;
     68         if (H[r] == -1) H[r] = L[size] = R[size] = size;
     69         else
     70         {
     71             L[size] = L[H[r]]; R[L[H[r]]] = size;
     72             R[size] = H[r]; L[H[r]] = size;
     73         }
     74         size++;
     75     }
     76     void remove(int c)
     77     {
     78         for (int i = D[c]; i != c; i = D[i])
     79             L[R[i]] = L[i], R[L[i]] = R[i];
     80     }
     81     void resume(int c)
     82     {
     83         for (int i = U[c]; i != c; i = U[i])
     84             L[R[i]] = R[L[i]] = i;
     85     }
     86     int h() ///用精确覆盖去估算剪枝
     87     {
     88         int ret = 0;
     89         bool vis[maxc];
     90         memset (vis, false, sizeof(vis));
     91         for (int i = R[0]; i; i = R[i])
     92         {
     93             if (vis[i])continue;
     94             ret++;
     95             vis[i] = true;
     96             for (int j = D[i]; j != i; j = D[j])
     97                 for (int k = R[j]; k != j; k = R[k])
     98                     vis[C[k]] = true;
     99         }
    100         return ret;
    101     }
    102     //根据具体问题选择限制搜索深度或直接求解。
    103     bool Dance(int k)
    104     {
    105         if (k + h() >= ans) return 0;
    106         if (!R[0])
    107         {
    108             if (k < ans)ans = k;
    109             return 1;
    110         }
    111         int c = R[0];
    112         for (int i = R[0]; i; i = R[i])
    113             if (S[i] < S[c])c = i;
    114         for (int i = D[c]; i != c; i = D[i])
    115         {
    116             remove(i);
    117             for (int j = R[i]; j != i; j = R[j])
    118                 remove(j);
    119             Dance(k + 1);
    120             for (int j = L[i]; j != i; j = L[j])
    121                 resume(j);
    122             resume(i);
    123         }
    124         return 0;
    125     }
    126     void initL(int x) ///col is 1~x,row start from 1
    127     {
    128         for (int i = 0; i <= x; ++i)
    129         {
    130             S[i] = 0;
    131             D[i] = U[i] = i;
    132             L[i + 1] = i; R[i] = i + 1;
    133         }///对列表头初始化
    134         R[x] = 0;
    135         size = x + 1; ///真正的元素从m+1开始
    136         memset (H, -1, sizeof(H));
    137         ///mark每个位置的名字
    138     }
    139 } dlx;
    140 
    141 int kase;
    142 int n;
    143 vector<int> vec;
    144 bool mtx[maxn][maxn];
    145 int row, col;
    146 bool vis[maxn];
    147 void init()
    148 {
    149     kase++;
    150     vec.clear();
    151     memset(mtx, 0, sizeof(mtx));
    152     memset(vis, 0, sizeof(vis));
    153 }
    154 void input()
    155 {
    156     scanf("%d", &n);
    157     int k;
    158     scanf("%d", &k);
    159     while (k--)
    160     {
    161         int x;
    162         scanf("%d", &x);
    163         vec.pb(x);
    164     }
    165 }
    166 void debug()
    167 {
    168     //
    169 }
    170 void calmtx()
    171 {
    172     row = 2 * n * (n + 1);
    173     col = 0;
    174     for (int i = 1; i <= n; i++)
    175         col += i * i;
    176 
    177     int cnt = 1;
    178     for (int si = 1; si <= n; si++)
    179     {
    180         for (int i = 1; i <= n - si + 1; i++)
    181         {
    182             for (int j = 1; j <= n - si + 1; j++)
    183             {
    184                 for (int k = 0; k < si; k++)
    185                 {
    186                     mtx[(i - 1) * (2 * n + 1) + j + k][cnt] = 1;
    187                     mtx[(i - 1 + si) * (2 * n + 1) + j + k][cnt] = 1;
    188                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1)][cnt] = 1;
    189                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1) + si][cnt] = 1;
    190                 }
    191                 cnt++;
    192             }
    193         }
    194     }
    195 }
    196 void build()
    197 {
    198     calmtx();
    199 
    200     dlx.initL(col);
    201     for (int i = 0; i < vec.size(); i++)
    202     {
    203         int x = vec[i];
    204         for (int j = 1; j <= col; j++)
    205             if (mtx[x][j] && !vis[j])
    206             {
    207                 vis[j] = 1;
    208                 dlx.R[dlx.L[j]] = dlx.R[j];
    209                 dlx.L[dlx.R[j]] = dlx.L[j];
    210                 dlx.R[j] = dlx.L[j] = 0;
    211             }
    212     }
    213     // for (int i = 1; i <= col; i++)
    214     //     cout << vis[i] << " ";
    215     // cout << endl;
    216     for (int i = 1; i <= row; i++)
    217     {
    218         for (int j = 1; j <= col; j++)
    219         {
    220             if (mtx[i][j] && !vis[j])
    221                 dlx.Link(i, j);
    222         }
    223     }
    224 }
    225 void solve()
    226 {
    227     build();
    228     // for (int i = 1; i <= row; i++)
    229     // {
    230     //     for (int j = 1; j <= col; j++)
    231     //     {
    232     //         cout << mtx[i][j] << " ";
    233     //     }
    234     //     cout << endl;
    235     // }
    236     // cout << row << " " << col << endl;
    237     dlx.ans = inf;
    238     dlx.Dance(0);
    239     printf("%d
    ", dlx.ans);
    240 }
    241 void output()
    242 {
    243     //
    244 }
    245 int main()
    246 {
    247     // int size = 256 << 20; // 256MB
    248     // char *p = (char *)malloc(size) + size;
    249     // __asm__("movl %0, %%esp
    " :: "r"(p));
    250 
    251     // std::ios_base::sync_with_stdio(false);
    252 #ifdef xysmlx
    253     freopen("in.cpp", "r", stdin);
    254 #endif
    255 
    256     kase = 0;
    257     int T;
    258     scanf("%d", &T);
    259     while (T--)
    260     {
    261         init();
    262         input();
    263         solve();
    264         output();
    265     }
    266     return 0;
    267 }
    POJ 1084
  • 相关阅读:
    3个常用基于Linux系统命令行WEB网站浏览工具(w3m/Links/Lynx)
    Linux进程关系
    Linux信号基础
    Linux进程基础
    Linux架构
    Linux文本流
    Linux文件管理相关命令
    Linux命令行与命令
    【转载】 input 输入格式化
    【所见即所得】textarea 精确限制字数、行数,中、英、全半角混检 。源码带注释
  • 原文地址:https://www.cnblogs.com/xysmlx/p/4000580.html
Copyright © 2020-2023  润新知