uva658 - It's not a Bug, it's a Feature! 状态压缩+隐式图搜索+优先队列的dijkstra

来源:互联网 发布:怎么更换mac屏保图片 编辑:程序博客网 时间:2024/06/06 21:41

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

It is a curious fact that consumers buying a new software product generally donot 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= \{b_1, b_2, \dots, b_n\}$ in their software. And they have releasedm patches$p_1, p_2, \dots, p_m$. To apply patchpi to the software, the bugs$B^+_i \subseteq B$ have to be present in the software, and the bugs$B^-_i \subseteq B$ must be absent (of course$B^+_i \cap B^-_i = \emptyset$ holds). The patch then fixes the bugs$F^-_i \subseteq B$ (if they have been present) and introduces the new bugs$F^+_i \subseteq B$ (where, again,$F^-_i \cap B^-_i = \emptyset$).

Tinyware's problem is a simple one. Given the original version of their software, which contains all the bugs inB, 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 integersn andm, the number of bugs and patches, respectively. These values satisfy$1 \le n \le 20$ and$1 \le m \le 100$. This is followed bym 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 ofn characters each.

The first of these strings describes the bugs that have to be present or absent before the patch can be applied. Thei-th position of that string is a ``+'' if bugbi has to be present, a ``-'' if bugbi 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. Thei-th position of that string is a ``+'' if bugbi is introduced by the patch, a ``-'' if bugbi is removed by the patch (if it was present), and a ``0'' if bugbi 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 alln 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.

  首先。。这个题肯定不是我自己想出来的。。太高端了,光题目意思就看了好久。参考了别人的思路。

  有N个bug和M个补丁,接下来M行给出这个补丁需要的时间,第一个字符串a是这个补丁只能在这种状态下才能使用,a[i]=='+'就是第i个漏洞必须存在,a[i]=='-'是第i个漏洞不能存在,a[i]==‘0’不要求。第二个串b,b[i]=='+'是使用这个补丁后第i个bug产生,b[i]=='-'是使用这个补丁后第i个bug被修复,b[i]=='0'还保持原来的状态不变。问最少需要多少时间修复所有的漏洞。

  主要思想是把每种状态用2进制表示,建图,起点为11111(n个,也就是2^n-1),用dijkstra算出终点状态(0)的最短路。。这题还必须要用优先队列的dijkstra,要不会超时。。。

  建图的时候dfs每种补丁能修复的所有状态,把这个能修复的状态和修复后的状态建立连接。因为要用优先队列的dijkstra,就要用到pair,定义结构体有y和t。定义的vector为结构体的类型的数组。

  优先队列的dijkstra方法:定义pii的优先队列priority_queue<pii,vector<pii>,greater<pii> >q; 先把起点和0加到优先队列里。当队列非空,每次取出d值最小的(如果不定义优先队列的比较函数,pair时默认先比较第一维),然后删除,也就是pii cur=q.top(),q.pop()。这时x=cur.second就是要加入的点了,如果x没有访问过,把x标记访问,再把跟x连接的点(有v[x].size()个)都更新重新加入队列(就算一个点被加入多次也没事,先取出的也是d值最小的那个)。最后d[0]就是答案。

  优先队列的dijkstra算法复杂度是O(MlogN),因为会把每条边算一遍,并且优先队列操作复杂度是O(logN)。


#include<cstring>#include<cstdio>#include<iostream>#include<cmath>#include<algorithm>#include<queue>#include<map>#include<vector>#define INF 0x3f3f3f3f#define pii pair<int,int>using namespace std;int N,M,T,P;int vis[1200000],d[1200000];char a[25],b[25];struct st{    int y,t;};vector<st> v[1200000];void add(int fa,int son){    st cur;    cur.y=son;    cur.t=T;    v[fa].push_back(cur);}void DFS(int cur,int *s){    if(cur>=N){        int fa=0,son=0,k;        for(int i=0;i<N;i++){            if(b[i]=='0') k=s[i];            if(b[i]=='+') k=1;            if(b[i]=='-') k=0;            son=(son<<1)+k;            fa=(fa<<1)+s[i];        }        add(fa,son);        return;    }    if(a[cur]=='0'){        s[cur]=0;        DFS(cur+1,s);        s[cur]=1;        DFS(cur+1,s);    }    if(a[cur]=='+'){        s[cur]=1;        DFS(cur+1,s);    }    if(a[cur]=='-'){        s[cur]=0;        DFS(cur+1,s);    }}void dijkstra(){    priority_queue<pii,vector<pii>,greater<pii> >q;    memset(vis,0,sizeof(vis));    memset(d,INF,sizeof(d));    d[P-1]=0;    q.push(make_pair(d[P-1],P-1));    while(!q.empty()){        pii cur=q.top();        q.pop();        int x=cur.second;        if(vis[x]) continue;        vis[x]=1;        int L=v[x].size();        for(int i=0;i<L;i++){            int y=v[x][i].y;            if(d[x]+v[x][i].t<d[y]){                d[y]=d[x]+v[x][i].t;                q.push(make_pair(d[y],y));            }        }    }    if(d[0]==INF) printf("Bugs cannot be fixed.\n\n");    else printf("Fastest sequence takes %d seconds.\n\n",d[0]);}int main(){    freopen("in.txt","r",stdin);    int cas=0;    while(scanf("%d%d",&N,&M),N||M){        P=1<<N;        for(int i=0;i<P;i++) v[i].clear();        while(M--){            scanf("%d%s%s",&T,a,b);            int c[25];            memset(c,0,sizeof(c));            DFS(0,c);        }        printf("Product %d\n",++cas);        dijkstra();    }    return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 织玻璃纤维网布环评怎么办 吃了受潮的奶粉怎么办 喝了受潮的奶粉怎么办 刚买的奶粉受潮怎么办 羊不小心吃了化肥怎么办 阿胶粉结成块了怎么办 半桶奶粉受潮了怎么办 眉粉受潮了结块怎么办 刚买的奶粉结块怎么办 袋装白糖成坨了怎么办 一袋子白糖硬了怎么办 粉饼上有一层油怎么办 葡萄后期氮肥施用过多怎么办 没洗的菜吃了怎么办 闻了汽油味头晕怎么办 碰到绿萝的汁液怎么办 吃了带农药水果怎么办 开槽模切一体机模切时开槽怎么办 柔版印刷走纸歪斜怎么办 美团外卖一天8单怎么办 单位显示器丢了怎么办员工赔 纸板板门起泡了怎么办 卖家要我开出质量问题证明怎么办 闲鱼买到的商品不符合描述怎么办 寄出去的东西碎了怎么办 闲鱼快递损坏了怎么办 寄快递东西坏了怎么办 快递邮寄东西坏了怎么办 快递被别人拆了怎么办 淘宝买的东西包装破损怎么办 寄血液被退回来怎么办 快递被安检扣了怎么办 淘宝原单退回运费怎么办 运输过程中包裹破损怎么办 天猫没收到货签收怎么办 收到的快递坏了怎么办 自寄的快递少了怎么办 邮的东西弄坏了怎么办 物流签收后发现货物损坏怎么办 发现客人损坏了酒店物品怎么办 东西坏了签收了怎么办