HDU 1818 It's not a Bug, It's a Feature! (图论SPFA)

来源:互联网 发布:网络销售股票违法吗 编辑:程序博客网 时间:2024/05/16 01:33

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): 138    Accepted Submission(s): 73


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

Recommend
linle
 

题意:给一个长度为nbug,和m个补丁,然后是m个补丁的描述。第一个数字是这个补丁消耗的时间。

1个字符串是这个补丁要工作需要满足的条件,第2个字符串是这个补丁的作用

 

详细一点说,

对于第一个字符串,假设是 -0-+0 -号代表这个位的bug不能出现,也就是不能有3号和5bug(定义最右边为1号,为了到时候方便位运算) +号就是指这个位bug一定要出现,也就是一定要有2bug0就是指……没什么意思。

满足上述条件该补丁才能起作用。

对于第二个字符串,假设是00--+-号代表这个补丁能杀掉这个位的bug,也就是杀掉2,3号。+号代表这个补丁会带来这个位的bug,也就是会新产生一个1bug

(假设bug长度为n,那么起始的时候,是1-n位都有bug,我们可以用一个二进制1111...1来表示)

 

8590499

2013-07-15 10:22:24

Accepted

1818

468MS

10516K

2007 B

C++

代码:
#include<cstdio>#include<cstring>#include<iostream>#include<queue>#define maxn 105#define maxv 1<<21#define INF 0x7ffffffusing namespace std;int n,m;char cstr[maxn],astr[maxn];bool vis[maxv];      int dis[maxv];int cost[maxn];int b[2][maxn];int p[2][maxn];void SPFA(){    queue<int> state;    for(int i=0;i<maxv;i++)    {        dis[i]=INF;        vis[i]=false;    }    int st=(1<<n)-1;    dis[st]=0;    state.push(st);    while(!state.empty())    {        int u=state.front();state.pop();vis[u]=false;        for(int i=0;i<maxn;i++)        {int v;            int tmp1=u|b[1][i];                 int tmp2=u&b[0][i];//tmp1==u说明状态u包含补丁使用时一定要存在的bug//tmp2==0说明状态u不包含不能存在的bug            if((tmp1==u)&&(tmp2==0))               {                v=u|p[1][i];         //增加bug                v=v&(~p[0][i]);      //消灭bug,相应的位置0if(dis[v]>dis[u]+cost[i]){dis[v]=dis[u]+cost[i];//printf("%d %d \n",v,dis[v]);if(!vis[v]){vis[v]=true;state.push(v);}}            }}    }}int main(){int cs=1;    while(scanf("%d%d",&n,&m)&&m&&n)    {memset(b,0,sizeof(b));memset(p,0,sizeof(p));        for(int i=0;i<m;i++)        {            scanf("%d%s%s",&cost[i],cstr,astr);             for(int j=0,k=n-1;j<n;j++,--k)            {                if(cstr[j]=='+')                    b[1][i]+=(1<<k);      //b[1][d]存第d个补丁用时一定要出现的bug                if(cstr[j]=='-')                    b[0][i]+=(1<<k);      //b[0][d]存第d个补丁用时一定不能出现的bug                if(astr[j]=='+')                    p[1][i]+=(1<<k);      //p[1][d]存增加的bug                if(astr[j]=='-')                    p[0][i]+=(1<<k);      //p[0][d]存消灭的bug            }        }        SPFA();printf("Product %d\n",cs++);        if(dis[0]==INF)            printf("Bugs cannot be fixed.\n");        else            printf("Fastest sequence takes %d seconds.\n",dis[0]);printf("\n");    }    return 0;}/*b=bug  p=patchcstr=condition string  astr=affect string把每个状态用整数表示,看做图中的点利用其二进制运算判断patch使用的条件和表示patch作用后的bug的状态。vis[i]表示i状态在不在队列中,true则在,反之不在dis[i]表示bug修复出现了i状态时候的最小时间。i状态也是一个整数。*/

感想:
1、位运算真的很强大!
2、而且用集合观点交集、并集来理解&、|很方便。
原创粉丝点击