• Dancing Links


    Dancing Links用来解决如下精确匹配的问题:

    选择若干行使得每一列恰好有一个1。Dancing Links通过对非零元素建立双向十字循环链表。上面的例子建立的链表如下所示:

    计算的时候使用搜索的策略。每次选出1最少的一列,比如c,然后选择这一列中的某一行,比如r,(r,c)=1,然后r中所有1所在的列,那些其他行这些列有1的都删掉(这些行不会在r算入答案后也在答案里,否则就有某些列多于一个1出现)。然后这就变成一个规模更小的问题,继续搜索。无解时要回溯。

      1 class CDancingLinks
      2 {
      3 protected:
      4     struct DancingLinksNode
      5     {
      6         DancingLinksNode* left;
      7         DancingLinksNode* right;
      8         DancingLinksNode* down;
      9         DancingLinksNode* up;
     10         int col;
     11         int row;
     12     };
     13 
     14     typedef DancingLinksNode Node;
     15 
     16     int *m_columnEleNumbers;
     17     int m_colNumber;
     18     int m_rowNumber;
     19     Node* m_pool;
     20     Node** m_head;
     21     int m_curUsePoolIndex;
     22 
     23 
     24 
     25 
     26 
     27     void _Remove(Node* cur)
     28     {
     29         --m_columnEleNumbers[cur->col];
     30         for(Node* p=cur->down;p!=cur;p=p->down)
     31         {
     32             p->left->right=p->right;
     33             p->right->left=p->left;
     34         }
     35     }
     36 
     37     void _Resume(Node* cur)
     38     {
     39         ++m_columnEleNumbers[cur->col];
     40         for(Node* p=cur->up;p!=cur;p=p->up)
     41         {
     42             p->left->right=p;
     43             p->right->left=p;
     44         }
     45     }
     46 
     47 
     48 
     49     bool _SearchSolution(const int depth,std::vector<int> &solution)
     50     {
     51         Node* p=_GetNode(0);
     52         if(p->left==p) return true;
     53 
     54         int Min=m_rowNumber+1;
     55         int MinColumnIndex=0;
     56         for(Node* q=p->left;q!=p;q=q->left)
     57         {
     58             if(m_columnEleNumbers[q->col]<Min)
     59             {
     60                 Min=m_columnEleNumbers[q->col];
     61                 MinColumnIndex=q->col;
     62             }
     63         }
     64 
     65 
     66         for(Node* q=_GetNode(MinColumnIndex)->down;q!=_GetNode(MinColumnIndex);q=q->down)
     67         {
     68             _Remove(q);
     69             solution.push_back(q->row);
     70             for(Node* rr=q->right;rr!=q;rr=rr->right) _Remove(rr);
     71             if(_SearchSolution(depth+1,solution)) return true;
     72             for(Node* rr=q->left;rr!=q;rr=rr->left) _Resume(rr);
     73             solution.pop_back();
     74             _Resume(q);
     75         }
     76 
     77         return false;
     78     }
     79 
     80     Node* _GetNode(int id) { return m_pool+id; }
     81 
     82     void _ReleaseMemory()
     83     {
     84          if(m_columnEleNumbers)
     85         {
     86             delete[] m_columnEleNumbers;
     87             m_columnEleNumbers=nullptr;
     88         }
     89 
     90         if(m_pool)
     91         {
     92             delete[] m_pool;
     93             m_pool=nullptr;
     94         }
     95         if(m_head)
     96         {
     97             delete[] m_head;
     98             m_head=nullptr;
     99         }
    100     }
    101 
    102 public:
    103 
    104     CDancingLinks():m_colNumber(-1),m_rowNumber(-1),
    105         m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr) {}
    106 
    107     /***
    108       列下标为[1,Column]
    109     ***/
    110     CDancingLinks(const int Column,const int Row):
    111         m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr)
    112     {
    113         SetSize(Column,Row);
    114     }
    115 
    116     /***
    117       列下标为[1,Column]
    118     ***/
    119     void SetSize(const int Column,const int Row)
    120     {
    121         m_colNumber=Column;
    122         m_rowNumber=Row;
    123 
    124         _ReleaseMemory();
    125 
    126         m_columnEleNumbers=new int[m_colNumber+1];
    127         m_pool=new Node[m_colNumber*(m_rowNumber+1)+1];
    128         m_head=new Node*[m_rowNumber+1];
    129         Clear();
    130     }
    131 
    132     void Clear()
    133     {
    134         for(int i=0;i<=m_colNumber;++i)
    135         {
    136             Node* cur=_GetNode(i);
    137             cur->left=((i==m_colNumber)?_GetNode(0):_GetNode(i+1));
    138             cur->right=((0==i)?_GetNode(m_colNumber):_GetNode(i-1));
    139             m_columnEleNumbers[i]=0;
    140 
    141             cur->up=cur->down=_GetNode(i);
    142             cur->col=i;
    143             cur->row=0;
    144         }
    145         for(int i=1;i<=m_rowNumber;++i) m_head[i]=NULL;
    146         m_curUsePoolIndex=m_colNumber+1;
    147     }
    148 
    149     ~CDancingLinks()
    150     {
    151         _ReleaseMemory();
    152     }
    153 
    154     void AddElement(const int row,const int col)
    155     {
    156 
    157         Node* cur=m_pool+(m_curUsePoolIndex++);
    158 
    159         cur->up=_GetNode(col);
    160         cur->down=_GetNode(col)->down;
    161         m_pool[col].down->up=cur;
    162         m_pool[col].down=cur;
    163 
    164 
    165         if(m_head[row]==NULL)
    166         {
    167             m_head[row]=cur->left=cur->right=cur;
    168         }
    169         else
    170         {
    171             cur->left=m_head[row]->left;
    172             cur->right=m_head[row];
    173             m_head[row]->left->right=cur;
    174             m_head[row]->left=cur;
    175         }
    176         ++m_columnEleNumbers[col];
    177         cur->col=col;
    178         cur->row=row;
    179     }
    180 
    181     bool GetSolution(std::vector<int> &Solution)
    182     {
    183         return _SearchSolution(0,Solution);
    184     }
    185 };
  • 相关阅读:
    oracle学习 五 使用存储过程创建一个重置密码为123456的功能(持续更新中)
    oracle学习 四(持续更新中)无法为表空间 MAXDATA 中的段创建 INITIAL 区
    P3224 [HNOI2012]永无乡
    P3521 [POI2011]ROT-Tree Rotations
    UVA11090 Going in Cycle!!
    P1136 迎接仪式
    P1984 [SDOI2008]烧水问题(具体证明)
    P1494 [国家集训队]小Z的袜子
    P2680 运输计划
    P2831 愤怒的小鸟
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/5990034.html
Copyright © 2020-2023  润新知