Dancing Links 重复覆盖问题~

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3498

这两天学习了Dancing Links  ,它主要对搜索的优化,尤其对于矩阵, 进行深搜的时候,随着层数的加深,矩阵会越来越稀疏,

如果还是用一般的遍历的话, 时间还是没变,还是遍历整个矩阵, 因为矩阵已经变稀疏了,这样做很显然的浪费时间,

这里用到Dancing Links,相信它优美的舞步,一定能打动你的。。

Dancing Links用到一个十字链表, 众所周知 链表对于插入和删除的处理 时间复杂度都是O(1), 这里就要用到链表的这一特性,

对矩阵的某一行或列进行删除的时候 ,先标记,之后把其删除, 等到搜索过后,再把其恢复,时间效率大大的提高。。

Dancing 一般用来解决精确覆盖的问题, 像本题属于 重复覆盖的问题, Dancing Links并不能优化多少,但是这里加一个评估函数,

就在很大的程度上提高了它的效率。、

题目大意:深渊领主有一个技能,溅射(分列攻击),当它把一个单位杀死的时候与该单位 直接 相连的所有单位都要被杀死,

给出n个单位之间的关系,问把这n个单位全部杀死,至少需要攻击多少次。

思路:n个单位排成一排,与该单位相连的单位,以及它自身,位于这一列, 即是Dancing links里面的0-1矩阵。

h函数是这样写的:

当前这种状态至少还需要攻击多少次才能把所有单位消灭。任选没有被标记的一个单位,然后把该列中每一个元素所对应的行,

该行中每一个元素所对应的单位都标记下来。 因为一般我们都只能选取 该列中的一个元素,然后进行处理, 这里把该列中所有的元素都选取出来

,然后进行处理,所需要的次数肯定要比一般情况下的少。。

我感觉吧,这个评估函数写的不够风骚,虽然我还没有想到更好的办法。 虽然他能把这题A掉,但是我感觉应该还会有更好的优化!

这道题应该算是一个比较裸的Dancing Links了。。

code:

View Code

  1 # include<stdio.h>  2 # include<string.h>  3 # define N 60  4 # define V N*N  5 int L[V],R[V];//记录左右方向的双向链表
  6 int U[V],D[V];//记录上下方向的双向链表  7 int C[V];//指向其列指针头的地址  8 int H[N];//行指针头  9 int S[N];//记录列链表中节点的总数 10 int size,n,m,ak; 11 int mark[N][N],visit[N]; 12 void Link(int r,int c) 13 { 14     S[c]++;C[size]=c; 15     U[size]=U[c];D[U[c]]=size; 16     D[size]=c;U[c]=size; 17     if(H[r]==-1) H[r]=L[size]=R[size]=size; 18     else 19     { 20         L[size]=L[H[r]];R[L[H[r]]]=size; 21         R[size]=H[r];L[H[r]]=size; 22     } 23     size++; 24 } 25 void remove(int Size) 26 { 27     int j; 28     for(j=D[Size];j!=Size;j=D[j]) 29         L[R[j]]=L[j],R[L[j]]=R[j]; 30 } 31 void resume(int Size) 32 { 33     int j; 34     for(j=D[Size];j!=Size;j=D[j]) 35         L[R[j]]=R[L[j]]=j; 36 } 37 int h() 38 { 39     int count=0,i,j,k; 40     memset(visit,0,sizeof(visit)); 41     for(i=R[0];i;i=R[i]) 42     { 43         if(visit[i]) continue; 44         count++; 45         for(j=D[i];j!=i;j=D[j]) 46         { 47             for(k=R[j];k!=j;k=R[k]) 48                 visit[C[k]]=1; 49         } 50     } 51     return count; 52 } 53 void Dance(int k) 54 { 55     int i,j,min,c; 56     if(k+h()>=ak) return; 57     if(!R[0]) 58     { 59         if(k<ak) ak=k; 60         return; 61     } 62     for(min=N,i=R[0];i;i=R[i]) 63         if(min>S[i]) min=S[i],c=i; 64     for(i=D[c];i!=c;i=D[i]) 65     { 66         remove(i); 67         for(j=R[i];j!=i;j=R[j]) 68             remove(j); 69         Dance(k+1); 70         for(j=R[i];j!=i;j=R[j]) 71             resume(j); 72         resume(i); 73     } 74 } 75 int main() 76 { 77     int i,j,a,b; 78     while(scanf("%d%d",&n,&m)!=EOF) 79     { 80         for(i=0;i<=n;i++) 81         { 82             S[i]=0; 83             U[i]=D[i]=i; 84             L[i+1]=i;R[i]=i+1; 85         }R[n]=0; 86         size=n+1; 87         memset(mark,0,sizeof(mark));     88         memset(H,-1,sizeof(H)); 89         while(m--) 90         { 91             scanf("%d%d",&a,&b); 92             mark[a][b]=mark[b][a]=1; 93         } 94         for(i=1;i<=n;i++) 95         { 96             for(j=1;j<=n;j++) 97             { 98                 if(mark[i][j] || i==j) Link(i,j); 99             }100         }101         ak=N;102         Dance(0);103         printf("%d\n",ak);104     }105     return 0;106 }

转载于:https://www.cnblogs.com/183zyz/archive/2011/08/07/2129801.html

hdu 3498 whosyourdaddy相关推荐

  1. hdu - 3498 - whosyourdaddy(重复覆盖DLX)

    题意:N(2 ≤ N ≤ 55)个点,M(0 ≤ M ≤ N*N)条无向边,删除一个点会把与其相邻的点一起删掉,问最少删几次可以删掉所有点. 题目链接:http://acm.hdu.edu.cn/sh ...

  2. HDU 3498 whosyourdaddy DLX重复覆盖

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=3498 题意: 有 n n个敌人,其中有mm对敌人互为邻居,当你攻击杀死一个敌人时,同时会杀死它所有的邻居 ...

  3. HDU 3498 whosyourdaddy(DLX重复覆盖)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3498         n个点,m条无向边,删除一个点会把与其相邻的点一起删掉,问最少删几次可以删掉所有 ...

  4. hdu - 3498 - whosyourdaddy(反复覆盖DLX)

    题意:N(2 ≤ N ≤ 55)个点,M(0 ≤ M ≤ N*N)条无向边,删除一个点会把与其相邻的点一起删掉.问最少删几次能够删掉全部点. 题目链接:http://acm.hdu.edu.cn/sh ...

  5. HDU 3498 whosyourdaddy (可重复覆盖舞蹈链)

    题意: 给出N个点,M个边构成图.每选取一个点都可以覆盖其相邻点,问要覆盖所有点最少选几个点 思路: 每个点都作为一个点集,进行爆搜覆盖,舞蹈链模板题. 代码: #include <bits/s ...

  6. HDU 3498 whosyourdaddy(Dancing_Links重复覆盖)

    题目地址 题意:给你n个城市,m条道路,每次摧毁一个城市会附带把与它直接连接的城市的摧毁,一个城市可以重复摧毁(如果不能重复就是精确覆盖了),问你最少摧毁多少个城市能把所有城市摧毁. 思路:我们可以构 ...

  7. hdu 3498 whosyourdaddy 重复覆盖

    #include <bits/stdc++.h> using namespace std; struct DLX {const static int maxn=64,maxm=64,max ...

  8. hdu 3498 whosyourdaddy (重复覆盖,DLX+迭代加深A*)

    题意:有一个英雄,他有一个技能,可以使一个点和与他相邻的点受到伤害,问最少攻击几个点可以使所有点至少被伤害一次. 思路:DLX.很裸.设行为每一个点,列为攻击点,在这里行元素与列元素都为n.然后DLX ...

  9. [DLX重复覆盖] hdu 3498 whosyourdaddy

    题意: 给N个怪,M个关系. 每个关系代表a和b是邻居. 然后问每次攻击你可以攻击一个怪以及它的全部邻居 问最少需要几次攻击能把怪全部杀死. 思路: 怪为行和列,然后对面每个怪的邻居都是这个怪的列建图 ...

最新文章

  1. Linux大神必会操作——系统排错
  2. 原生 js 上传图片
  3. 满园尽是503,记曾经的一次IIS 7性能考验
  4. pytorch训练过程中loss出现NaN的原因及可采取的方法
  5. python手机版iphone-Python编程神器
  6. 两个条件一个为false就运行_Python入门基础实例讲解——两个数字比大小,并输出最大值...
  7. 蓝桥杯历届试题 国王的烦恼(并查集逆序加边+坑)
  8. mysql----innodb统计信息
  9. java swarm集群_52个Java程序员不可或缺的 Docker 工具
  10. 东京奥运出租车超预算想找滴滴接盘被拒 网友:真当人傻吗?
  11. php论坛权限设置,php – 如何实现论坛权限
  12. python数据导出excel_【python Excel】如何使用python将大量数据导出到Excel中的小技巧之一...
  13. PHP问题 —— The use statement with non-compound name
  14. H264的RTP负载打包的数据包格式,分组,分片
  15. 结构体定义 typedef struct LNode 用法说明
  16. vivo是安卓手机吗_拜托你看看vivo手机自带的翻译功能,这么强大的功能浪费了合适吗...
  17. vs2015智能提示英文改为中文
  18. OneTab插件的替代产品-OneTab Pro
  19. nginx端口映射配置(Windows)
  20. 易语言子程序和C语言子程序,一步一步跟我学易语言之认识窗口组件和子程序...

热门文章

  1. LP、HPM、HPC、HPC等工艺制作博文
  2. 江苏省工业互联网标识创新应用案例集
  3. Python-scrapy爬取起点榜单信息
  4. Shell之$(cd $(dirname $0); pwd)命令详解
  5. Spring boot mybatis 打印SQL语句
  6. 【面经】高德地图 C++ 研发 一面
  7. 网络阶段测试理论摘要
  8. 水星mac1300r虚拟服务器,水星(MERCURY)MAC1300R无线路由器怎么设置? | 192路由网
  9. RecyclerView详细用法
  10. Linux 刻录CD/DVD命令 growisofs/mkisofs/cdrecord