UVA658 这不是bug,而是特性 It‘s not a Bug, it‘s a Feature!

  • 题意:补丁在修正BUG时,有时也会引入新的BUG,假定有n(n<=20)n(n<=20) 个潜在BUG,和m(m<=100)m(m<=100) 个补丁,每个补丁用两个长度为nn 的字符串表示,其中字符串的每个位置表示一个bug,第一个串表示打补丁之前的状态(“-”表示该BUG必须不存在,“+”表示该补丁必须存在,0表示无所谓),第二串表示打补丁之后的状态(”-“表示不存在,“+”表示存在,0表示不变)。每个补丁有一定的执行时间,你的任务是用最小的时间把所有BUG都存在的软件变得没有BUG。
  • 考虑建图状态压缩,每个状态用一个二进制数表示,0表示‘+’,1表示‘-’,如样例中的-++可表示为(2)100即(10)7;这样每一个状态都可以看成图中的一个点,点与点之间路径的权值则为对应补丁的花费;原题装换成了一个起点为0,终点为2的n次方减1的单源最短路问题。
  • *如何松弛?*结点很多,多达2的n次方个,但是补丁的总数只有100个,因此在尝试去松弛时可以遍历这100个补丁,这样相当于每个在**集合(队列)**中的点只有100条出边。
  • *如何判断一个状态转移是否合法?*一下为几个位运算技巧:
    (A>>n-1)&1用于判断二进制数A从右到左第n位是否为1
    A=A|(1< A=A&(~(1< 注意,这里的第n位指的是下标从零开始的第n位(0··1··2···n-1);
  • 代码:状态计算的部分其实可以继续用位运算优化。
#include 
#include 
#include 
using namespace std;
const int maxn=(1<<20)+5;
int n,m,d[maxn],num;
struct node{
    int u,w;
    string s1,s2;
}no[120];
struct heapnode{
    int u,d;
    bool operator<(const heapnode & a)const{
    return d>a.d;}
};
bool dijkstra()
{
    for(int i=0;i<=(1<<n)-1;i++)
    d[i]=0x3f3f3f3f;
    d[0]=0;
    priority_queue<heapnode>q;
    q.push((heapnode){0,0});
    while(!q.empty())
    {
        heapnode x=q.top();
        q.pop();
        if(x.d!=d[x.u]) continue;
        int u=x.u;
        for(int i=1;i<=m;i++)
        {
            int tmp=0;bool bug=0;
            for(int j=0;j<n;j++)
            {
                if(no[i].s1[j]!='0')
                {
                    bool k=no[i].s1[j]=='+'?0:1;
                    if(((u>>(n-j-1))&1)!=k)
                    {
                        bug=1;
                        break;
                    }
                }
            }
            if(!bug)
            {
                for(int j=0;j<n;j++)
                {
                    if(no[i].s2[j]!='0')
                    {
                        bool k=no[i].s2[j]=='+'?0:1;
                        tmp+=k*(1<<(n-j-1));
                    }
                    else{
                        bool k=((u>>(n-j-1))&1);
                        tmp+=k*(1<<(n-j-1));
                    }
                }

                if(d[tmp]>d[u]+no[i].w)
                {
                    d[tmp]=d[u]+no[i].w;
                    q.push((heapnode){tmp,d[tmp]});
                }
            }
        }
    }
    if(d[(1<<n)-1]!=0x3f3f3f3f)
        return 1;
    return 0;
}
int main()
{
//    freopen("1.txt","w",stdout);
    while(cin>>n>>m&&n)
    {
        for(int i=1;i<=m;i++)
        cin>>no[i].w>>no[i].s1>>no[i].s2;
        cout<<"Product "<<++num<<endl;
        if(dijkstra())
        cout<<"Fastest sequence takes "<<d[(1<<n)-1]<<" seconds."<<endl;
        else
        cout<<"Bugs cannot be fixed."<<endl;
        cout<<endl;
    }
    return 0;
}

你可能感兴趣的:(UVA,图论)