• hust 1017


    题意:求01矩阵的精确覆盖。

    分析:本来想学习dancing links来解决数独问题,发现dancing links最初解决的问题是精确覆盖,于是就找到这道题来做了。这种NPC问题只能用DFS暴搜的情况下,很适合的一种优化方式就是用dancing links加速状态的改变,利用双向循环十字链表使元素的删除与恢复操作非常简便快捷。

      1 #include <cstdio>
      2 
      3 int U[102005],D[102005],L[102005],R[102005];
      4 int X[100005],Y[100005],H[1005],S[1005],ans[1005],len,M,N,sz;
      5 
      6 void init(int n,int m)
      7 {
      8     for(int i = 0;i <= m;i++)
      9     {
     10         U[i] = D[i] = i;
     11         L[i + 1] = i;
     12         R[i] = i + 1;
     13         S[i] = 0;
     14     }
     15     R[m] = 0;
     16     L[0] = m;
     17     sz = m + 1;
     18 }
     19 
     20 void remove(int c)
     21 {
     22     //删除一整列
     23     R[L[c]] = R[c];
     24     L[R[c]] = L[c];
     25     //删除行
     26     for(int i = D[c];i != c;i = D[i])
     27     {
     28         for(int j = R[i];j != i;j = R[j])
     29         {
     30             D[U[j]] = D[j];
     31             U[D[j]] = U[j];
     32             S[X[j]]--;
     33         }
     34     }
     35 }
     36 
     37 void resume(int c)
     38 {
     39     //恢复一整列
     40     L[R[c]] = c;
     41     R[L[c]] = c;
     42     //恢复行
     43     for(int i = D[c];i != c;i = D[i])
     44     {
     45         for(int j = R[i];j != i;j = R[j])
     46         {
     47             D[U[j]] = j;
     48             U[D[j]] = j;
     49             S[X[j]]++;
     50         }
     51     }
     52 }
     53 
     54 void ins(int r,int c)
     55 {
     56     S[c]++;
     57     //纵向插入
     58     D[U[c]] = sz;
     59     U[sz] = U[c];
     60     D[sz] = c;
     61     U[c] = sz;
     62     X[sz] = c;
     63     Y[sz] = r;
     64     //横向插入
     65     if(H[r] == -1)
     66     {
     67         H[r] = L[sz] = R[sz] = sz;
     68     }
     69     else
     70     {
     71         R[L[H[r]]] = sz;
     72         L[sz] = L[H[r]];
     73         R[sz] = H[r];
     74         L[H[r]] = sz;
     75     }
     76     sz++;
     77 }
     78 
     79 bool dfs(int k)
     80 {
     81     if(R[0] == 0)
     82     {
     83         len = k;
     84         ans[k] = -1;
     85         return true;
     86     }
     87     else
     88     {
     89         int m = 0xffffff,num;
     90         for(int i = R[0];i != 0;i = R[i])
     91         {
     92             if(S[i] == 0)
     93             {
     94                 return false;
     95             }
     96             if(m > S[i])
     97             {
     98                 m = S[i];
     99                 num = i;
    100                 if(m == 1)
    101                 {
    102                     break;
    103                 }
    104             }
    105         }
    106         remove(num);
    107         for(int i = D[num];i != num;i = D[i])
    108         {
    109             ans[k] = Y[i];
    110             for(int j = R[i];j != i;j = R[j])
    111             {
    112                 remove(X[j]);
    113             }
    114             if(dfs(k + 1))
    115             {
    116                 return true;
    117             }
    118             for(int j = R[i];j != i;j = R[j])
    119             {
    120                 resume(X[j]);
    121             }
    122         }
    123         resume(num);
    124     }
    125     return false;
    126 }
    127 
    128 int main()
    129 {
    130     while(~scanf("%d%d",&N,&M))
    131     {
    132         init(N,M);
    133         for(int i = 1;i <= N;i++)
    134         {
    135             int k;
    136             scanf("%d",&k);
    137             H[i] = -1;
    138             for(int j = 1;j <= k;j++)
    139             {
    140                 int c;
    141                 scanf("%d",&c);
    142                 ins(i,c);
    143             }
    144         }
    145         if(dfs(0))
    146         {
    147             printf("%d",len);
    148             for(int i = 0;ans[i] != -1;i++)
    149             {
    150                 printf(" %d",ans[i]);
    151             }
    152             printf("
    ");
    153         }
    154         else
    155         {
    156             printf("NO
    ");
    157         }
    158     }
    159     return 0;
    160 }
  • 相关阅读:
    json字符串与java对象的相互转换(jackson)
    EventBus的使用
    android 定时任务
    使用FlaycoBanner实现图片轮播效果(加载网络图片)
    okHttp使用
    Android 终于官方支持按百分比来设置控件的宽高了
    Android下使用Properties文件保存程序设置
    google vr开源 cardboard
    Android开源控件PhotoView的使用
    Android 布局优化
  • 原文地址:https://www.cnblogs.com/ZShogg/p/3288980.html
Copyright © 2020-2023  润新知