【题意】

补丁在修正\(BUG\)时,有时也会引入新的\(BUG\),假定有\(n(n<=20)\)个潜在\(BUG\),和\(m(m<=100)\)个补丁,每个补丁用两个长度为\(n\)的字符串表示,其中字符串的每个位置表示一个\(BUG\),第一个串表示打补丁之前的状态 (“-”表示该\(BUG\)必须不存在,“+”表示该补丁必须存在,0表示无所谓),第二串表示打补丁之后的状态 ("-"表示不存在,"+"表示存在,"0"表示不变)。每个补丁有一定的执行时间,你的任务是用最小的时间把所有BUG都存在的软件变得没有\(BUG\)。

【算法】

\(\text{隐式图}\)\(SPFA\)

【分析】

在任意时刻,每个\(BUG\)可能存在也可能不存在,所以可以用\(n\)位二进制串来表示当前软件的状态。打完补丁之后,软件的BUG状态会发生改变,对应状态转移。是不是很像动态规划?可惜动态规划是行不通的,因为状态经过多次转移之后可能会回到以前的状态,即状态图并不是DAG。如果直接用记忆化搜索,会出现无限递归

正确的方法是把状态看成点,状态转移看成边,转化成图论中的最短路径问题,然后使用\(Dijkstra\)或\(Bellman-Ford\)算法进行求解。不过这道题和普通的最短路径问题不一样:节点很多,有\(2^n\)个,而且很多状态根本遇不到(即不管怎么打补丁,也不可能打成那种状态),所以没有必要先将原图存储好

孩子咳嗽老不好, 怎么办呢?

这里介绍一种 "隐式图" 的方法,当需要得到某个点的所有边时,不是去读\(G[u]\),而是直接枚举这\(m\)个补丁是否打的上。不管是\(Dijkstra\)还是\(Bellman-Ford\)算法,这个方法都适用。

  • 一些本题的其他小技巧

得到\(x\)的二进制右起第\(i\)位:x>>(i-1)&1

把\(x\)二进制的右起第\(i\)位替换为\(a\)(\(a\)或\(0\)或\(1\)):x^=(x&(1<<(i-1)))^(a<<(i-1))

【代码】

思路也说得很清楚了,这里就不写注释了

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN=20+10,MAXM=100+10;
  4. int n,m;
  5. struct Node
  6. {
  7. int t;
  8. int a[MAXN];
  9. int b[MAXN];
  10. }patch[MAXM];
  11. int d[2000000];
  12. int T;
  13. inline void init(int k)
  14. {
  15. cin>>patch[k].t;
  16. string s;
  17. cin>>s;
  18. for(int i=0;i<s.size();i++)
  19. {
  20. if(s[i]=='-')patch[k].a[i+1]=-1;
  21. else if(s[i]=='0')patch[k].a[i+1]=0;
  22. else patch[k].a[i+1]=1;
  23. }
  24. cin>>s;
  25. for(int i=0;i<s.size();i++)
  26. {
  27. if(s[i]=='-')patch[k].b[i+1]=-1;
  28. else if(s[i]=='0')patch[k].b[i+1]=0;
  29. else patch[k].b[i+1]=1;
  30. }
  31. }
  32. inline bool check(int sum,int k)
  33. {
  34. for(int i=1;i<=n;i++)
  35. {
  36. if(patch[k].a[i]==0)continue;
  37. if(patch[k].a[i]==-1 && (sum>>(n-i)&1)==0 )continue;
  38. if(patch[k].a[i]==1 && (sum>>(n-i)&1)==1 )continue;
  39. return 0;
  40. }
  41. return 1;
  42. }
  43. inline int get(int sum,int k)
  44. {
  45. for(int i=1;i<=n;i++)
  46. {
  47. if(patch[k].b[i]==0)continue;
  48. if(patch[k].b[i]==-1)sum^=(sum&(1<<(n-i)))^(0<<(n-i));
  49. else sum^=(sum&(1<<(n-i)))^(1<<(n-i));
  50. }
  51. return sum;
  52. }
  53. inline void SPFA()
  54. {
  55. memset(d,0x3f,sizeof(d));
  56. queue<int>q;
  57. q.push((1<<n)-1);
  58. d[(1<<n)-1]=0;
  59. while(q.size())
  60. {
  61. int now=q.front();
  62. //cout<<now<<endl;
  63. q.pop();
  64. for(int i=1;i<=m;i++)
  65. {
  66. if(!check(now,i))continue;
  67. int x=get(now,i);
  68. //cout<<x<<endl;
  69. if(d[now]+patch[i].t<d[x])
  70. {
  71. d[x]=d[now]+patch[i].t;
  72. q.push(x);
  73. }
  74. }
  75. }
  76. }
  77. int main()
  78. {
  79. //ios::sync_with_stdio(false);
  80. while(cin>>n>>m)
  81. {
  82. if(n==0&&m==0)break;
  83. T++;
  84. for(int i=1;i<=m;i++)
  85. init(i);
  86. //cout<<patch[1].a[1]<<" "<<patch[1].a[2]<<" "<<patch[1].a[3]<<endl;
  87. SPFA();
  88. printf("Product %d\n",T);
  89. if(d[0]==0x3f3f3f3f)
  90. printf("Bugs cannot be fixed.\n");
  91. else
  92. printf("Fastest sequence takes %d seconds.\n",d[0]);
  93. cout<<endl;
  94. }
  95. return 0;
  96. }

刘汝佳大法好!

洛谷 题解 UVA658 【这不是bug,而是特性 It's not a Bug, it's a Feature!】的更多相关文章

  1. 洛谷 题解 UVA572 【油田 Oil Deposits】

    这是我在洛谷上的第一篇题解!!!!!!!! 这个其实很简单的 我是一只卡在了结束条件这里所以一直听取WA声一片,详细解释代码里见 #include<iostream> #include&l ...

  2. 洛谷 题解 P1600 【天天爱跑步】 (NOIP2016)

    必须得说,这是一道难题(尤其对于我这样普及组205分的蒟蒻) 提交结果(NOIP2016 天天爱跑步): OJ名 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 Libre ...

  3. 洛谷题解P4314CPU监控--线段树

    题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...

  4. 洛谷题解 P1592 【互质】

    原题传送门 题目描述 输入两个正整数n和k,求与n互质的第k个正整数. 输入格式 仅一行,为两个正整数n(≤10^6)和k(≤10^8). 输出格式 一个正整数,表示与n互质的第k个正整数. 输入输出 ...

  5. 洛谷题解 CF777A 【Shell Game】

    同步题解 题目翻译(可能有童鞋没读懂题面上的翻译) 给你三张牌0,1,2. 最初选一张,然后依次进行n次交换,交换规则为:中间一张和左边的一张,中间一张和右边一张,中间一张和左边一张...... 最后 ...

  6. 洛谷题解 CF807A 【Is it rated?】

    同步题解 题目 好吧,来说说思路: 1.先读入啦~(≧▽≦)/~啦啦啦 2.判断a[i]赛前赛后是否同分数,如果分数不同,则输出,return 0 . 3.如果同分数,则判断a[i]赛前(或赛后)是否 ...

  7. 洛谷题解 P1138 【第k小整数】

    蒟蒻发题解了 说明:此题我用的方法为桶排(我翻了翻有人用了桶排只不过很难看出来,可能有些重复的,这个题只是作为一个专门的桶排来讲解吧) (不会算抄袭吧 ‘QWaWQ’) 简单来说(会的人跳过就行): ...

  8. 【洛谷题解】P2303 [SDOi2012]Longge的问题

    题目传送门:链接. 能自己推出正确的式子的感觉真的很好! 题意简述: 求\(\sum_{i=1}^{n}gcd(i,n)\).\(n\leq 2^{32}\). 题解: 我们开始化简式子: \(\su ...

  9. 洛谷题解 P2865 【[USACO06NOV]路障Roadblocks】

    链接:https://www.luogu.org/problemnew/show/P2865 题目描述 Bessie has moved to a small farm and sometimes e ...

随机推荐

  1. HTML 基础知识(特殊字符的转义)

    1. body.head(meta) <body></body>标签的常见属性: bgcolor:整个页面的背景: text:设置文本颜色 link:设置连接颜色(),vlin ...

  2. 解析Android的 消息传递机制Handler

    1. 什么是Handler: Handler 网络释义"机械手.经理"意思,在Android它用于管理多个线程UI操作: 2. 为什么会出现Handler: 在Android里面的 ...

  3. WPF 导出资源文件

    在wpf开发中我们可以把各种文件.图片打包到项目中也就是应用程序资源文件,然后在项目中可以通过特定的uri格式去调用.那有些时候为了方便我们可能想要在程序中将资源文件导出来使用,那么怎么做呢? 第 1 ...

  4. WPF用Blend写的交通信号灯

    原文:WPF用Blend写的交通信号灯 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/1 ...

  5. MIT墙上的格言(如果你把任务留到最后一分钟,那么你一定能在一分钟内完成任务)

    1,永远不能忘记傅立叶变换. Never far no can forget Fuliye changer. 2,盲目的研究者就像法拉第和麦克斯韦之间的电学家一样无所适从. Blind Eye's r ...

  6. WPF 后台C#设置控件背景图片

    原文:WPF 后台C#设置控件背景图片 以前的程序中有做过,当时只是记得uri很长一大段就没怎么记.今天有人问了也就写下来.   这是一个Button,设置了Background后的效果. 前台的设置 ...

  7. Spring框架:Spring安全

    在传统的Web发展,安全码被分散在各个模块,这样方便管理,有时你可能会错过一个地方导致安全漏洞.为了解决这个问题,它的发明Spring Security.它是业务逻辑的有关安全代码的作用全部转移到一个 ...

  8. Android Intent传递对象摘要

    效果: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaG9uZ3NoZW5ncGVuZw==/font/5a6L5L2T/fontsize/400/fil ...

  9. Java之java.lang.IllegalMonitorStateException

    今天又中彩了, 原本很简单的多线程程序, 蓦然间冒了个"java.lang.IllegalMonitorStateException" , 杀了个措手不及. 一直纳闷, 为什么为什 ...

  10. 通通玩blend美工(8)——动态绘制路径动画,画出个萌妹子~

    原文:通通玩blend美工(8)--动态绘制路径动画,画出个萌妹子~ 2年前我在玩Flex的时候就一直有一个疑问,就是如何来实现一个蚊香慢慢烧完的Loading动画呢? 刚经历了某甲方高强度一个月的洗 ...