HDU 1818 It's not a Bug, It's a Feature! 最短路

来源:互联网 发布:打淘宝发货单要用什么 编辑:程序博客网 时间:2024/04/29 00:54

It's not a Bug, It's a Feature!

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 160    Accepted Submission(s): 80


Problem Description
It is a curious fact that consumers buying a new software product generally do not expect the software to be bug-free. Can you imagine buying a car whose steering wheel only turns to the right? Or a CD-player that plays only CDs with country music on them? Probably not. But for software systems it seems to be acceptable if they do not perform as they should do. In fact, many software companies have adopted the habit of sending out patches to fix bugs every few weeks after a new product is released (and even charging money for the patches).
Tinyware Inc. is one of those companies. After releasing a new word processing software this summer, they have been producing patches ever since. Only this weekend they have realized a big problem with the patches they released. While all patches fix some bugs, they often rely on other bugs to be present to be installed. This happens because to fix one bug, the patches exploit the special behavior of the program due to another bug.

More formally, the situation looks like this. Tinyware has found a total of n bugs B = {b1, b2, ..., bn} in their software. And they have released m patches p1, p2, ..., pm. To apply patch pi to the software, the bugs Bi+ in B have to be present in the software, and the bugs Bi- in B must be absent (of course Bi+ ∩ Bi- = Φ). The patch then fixes the bugs Fi- in B (if they have been present) and introduces the new bugs Fi+ in B (where, again, Fi+ ∩ Fi- = Φ).

Tinyware's problem is a simple one. Given the original version of their software, which contains all the bugs in B, it is possible to apply a sequence of patches to the software which results in a bug- free version of the software? And if so, assuming that every patch takes a certain time to apply, how long does the fastest sequence take?

 

Input
The input contains several product descriptions. Each description starts with a line containing two integers n and m, the number of bugs and patches, respectively. These values satisfy 1 <= n <= 20 and 1 <= m <= 100. This is followed by m lines describing the m patches in order. Each line contains an integer, the time in seconds it takes to apply the patch, and two strings of n characters each.

The first of these strings describes the bugs that have to be present or absent before the patch can be applied. The i-th position of that string is a ``+'' if bug bi has to be present, a ``-'' if bug bi has to be absent, and a `` 0'' if it doesn't matter whether the bug is present or not.

The second string describes which bugs are fixed and introduced by the patch. The i-th position of that string is a ``+'' if bug bi is introduced by the patch, a ``-'' if bug bi is removed by the patch (if it was present), and a ``0'' if bug bi is not affected by the patch (if it was present before, it still is, if it wasn't, is still isn't).

The input is terminated by a description starting with n = m = 0. This test case should not be processed.
 

Output
For each product description first output the number of the product. Then output whether there is a sequence of patches that removes all bugs from a product that has all n bugs. Note that in such a sequence a patch may be used multiple times. If there is such a sequence, output the time taken by the fastest sequence in the format shown in the sample output. If there is no such sequence, output ``Bugs cannot be fixed.''.

Print a blank line after each test case.
 

Sample Input
3 31 000 00-1 00- 0-+2 0-- -++4 17 0-0+ ----0 0
 

Sample Output
Product 1Fastest sequence takes 8 seconds.Product 2Bugs cannot be fixed.
 

Source
Southwestern European Regional Contest 1998

传送门:HDU 1818 It's not a Bug, It's a Feature!

题目大意:补丁在修正bug时,有时也会引入新的bug。假定有n( n <= 20 )个潜在bug和m( m <= 100 )个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug。
第一个串表示打补丁之前的状态( " - " 表示该补丁必须不存在," + " 表示必须存在,0 表示无所谓),第二个串表示打补丁之后的状态( " - " 表示不存在," + " 表示存在,0 表示不改变)。每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没有bug。一个补丁可以打任意多次。

题目分析:
对于这题我们用最短路来做就好了,为了效率我们用二进制来优化。
对于bug串,相对位置为0表示没有bug,相对位置为1表示有bug。
对于补丁串:对打补丁之前的状态表示的串,我们分别保存必须存在的补丁(1表示存在,0表示无关)和必须不存在的补丁(1表示不存在,0表示无关)对打补丁之后的状态表示的串,我们分别保存打完后存在的补丁(1表示存在,0表示无关)和打完后不存在的补丁(1表示不存在,0表示无关)。这样就用了四个变量记录四种情况。
然后最短路的时候,直接对每个有的状态暴力枚举所有的补丁串看是否能打上。
本题我用了最小优先队列,由于优先队列的特性,我直接不保存最小值了,反正最后取出来的必定是最小值。
本题也是一道很好的二进制优化的题,建议多多思考二进制的玄妙 ^ w ^

代码如下:

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std ;#define clear(A, X) memset ( A , X , sizeof A )const int maxN = 1048577 ;//1024 * 1024 + 1const int maxM = 128 ;const int maxH = 1048577 ;//1024 * 1024 + 1struct Node {int   no_bug_pre ;//打前必须存在int have_bug_pre ;//打前必须不存在int   no_bug_now ;//打后不存在int have_bug_now ;//打后存在int w ;//消耗的时间} a[ maxM ] ;//补丁串struct Heap {int d , num ;} heap[ maxH ] ;//优先队列int n , m , top ;char s1[ maxM ] , s2[ maxM ] ;bool done[ maxN ] ;void swap ( Heap &X , Heap &Y ) {Heap tmp ;tmp =   X ;X   =   Y ;Y   = tmp ;}void push ( int d , int num ) {Heap tmp = { d , num } ;heap[ top ] = tmp ;int o = top ++ , p = ( o - 1 ) / 2 ;while ( o && heap[ o ].d < heap[ p ].d ) {swap ( heap[ o ] , heap[ p ] ) ;o = p ;p = ( o - 1 ) / 2 ;}}Heap pop () {Heap ans = heap[ 0 ] ;heap[ 0 ] = heap[ -- top ] ;int o = 0 , tmp = o , l = o * 2 + 1 , r = o * 2 + 2 ;while ( 1 ) {if ( l < top && heap[ l ].d < heap[ tmp ].d ) tmp = l ;if ( r < top && heap[ r ].d < heap[ tmp ].d ) tmp = r ;if ( tmp == o ) break ;swap ( heap[ tmp ] , heap[ o ] );o = tmp ;tmp = o ;l = o * 2 + 1 ;r = o * 2 + 2 ;}return ans ;}void init () {for ( int i = 0 ; i < m ; ++ i ) {scanf ( "%d%s%s" , &a[ i ].w , s1 , s2 ) ;a[ i ].have_bug_pre = a[ i ].have_bug_now = a[ i ].no_bug_pre = a[ i ].no_bug_now = 0 ;for ( int j = 0 ; j < n ; ++ j ) {if ( s1[ j ] == '+' ) a[ i ].have_bug_pre += ( 1 << j ) ;if ( s1[ j ] == '-' ) a[ i ].no_bug_pre   += ( 1 << j ) ;if ( s2[ j ] == '+' ) a[ i ].have_bug_now += ( 1 << j ) ;if ( s2[ j ] == '-' ) a[ i ].no_bug_now   += ( 1 << j ) ;}}}void Dijkstra () {clear ( done , 0 ) ;top = 0 ;push ( 0 , ( 1 << n ) - 1 ) ;//初始状态全为1表示bug全部存在while ( top ) {Heap u = pop () ;if ( !u.num ) {//存在可行方案printf ( "Fastest sequence takes %d seconds.\n\n" , u.d ) ;return ;}if ( done[ u.num ] ) continue ;done[ u.num ] = 1 ;for ( int i = 0 ; i < m ; ++ i ) {int x = u.num ;int X = x | a[ i ].have_bug_pre ;//X = x:相对位置bug必须存在 ———— 满足int Y = x & a[ i ].no_bug_pre ;//Y = 0:相对位置bug必须没有 ———— 满足if ( X == x && Y == 0 ) {//printf ( "%d : %d -> " , i , x ) ;x &= ~a[ i ].no_bug_now ;//消灭bugx |=  a[ i ].have_bug_now ;//产生bug//printf ( "%d\n" , x ) ;push ( u.d + a[ i ].w , x ) ;}}}//不存在可行方案printf ( "Bugs cannot be fixed.\n\n" ) ;}void work () {init () ;Dijkstra () ;}int main () {int cas = 0 ;while ( ~scanf ( "%d%d" , &n , &m ) && ( n || m ) ) {printf ( "Product %d\n" , ++ cas ) ;work () ;}return 0 ;}


0 0
原创粉丝点击