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

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

很棒的一道最短路的题 ,首先是得能看出是最短路。。。要不是在最短路专题里做到它,肯定就想拿状压dp去做了,但会成环,所有并不能用状压dp去做,正确的方法 就想刘汝佳书上说的那样,把状态看出节点,但不预先处理出边,而是在读到点u时,遍历所有的补丁来处理出边。注意处理边是不能太暴力,要跟状压dp里处理状态一样,用2进制的各种运算来处理,才不会T掉。

这里重点解释一下go()里的 补丁处理 输入为当前状态 和补丁序号 每个补丁里面存 a0是补丁要求状态里0(0是有bug)的位置,所有应该是0的地方在2进制的对应位赋成1 这样当前状态和a0取& 就是把这些应该为0的位取出来 ,为0 才满足补丁要求。其他操作同理。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
typedef pair pii;
const int inf=214748367;
const int M=1000+5;
//挺实用的 复杂度O(Elog((N)) 其实要小很多
priority_queue,greater >q;
int n,m,w;
struct DEBUG
{
    int a0,a1,b0,b1;
    int v;
} bu[105];
int d[5548576];
int now[105]= {0};
int go(int u,int id)
{
    if((u&bu[id].a0)!=0)return -1;
    if((u&bu[id].a1)!=bu[id].a1)return -1;
    u|=bu[id].b1;
    u-=u&bu[id].b0;
    return u;
}
int Dijkstra(int u)
{
    while(!q.empty())q.pop();
    for(int i=0; i<=n; i++) d[i]=i==u?0:inf;
    q.push({0,u});
    while(!q.empty())
    {
        pii x=q.top();
        q.pop();
       // if(x.first>d[n])return 0;
        if(x.first!=d[x.second])continue;
        int u=x.second;
        for(int i=0; id[u]+bu[i].v)
            {
                d[e]=d[u]+bu[i].v;
                q.push({d[e],e});
            }
        }
    }
}
int pow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res*=a;
        a*=a;
        b>>=1;
    }
    return res;
}
char A[105],B[105];
// + = 0 = bug
int main()
{
    int cnt=0;
    while(~scnaf("%d%d",&w,&m)&&w+m)
    {
        n=pow(2,w)-1;
        for(int i=0; i


你可能感兴趣的:(最短路,最短路)