It‘s not a Bug, it‘s a Feature!(UVA 658)

题目
题意
首先给出n和m,表示有n个bug和m个补丁。一开始存在n个bug,用1表示一个bug存在0表示不存在,所以一开始就是n个1,我们的目的是要消除所有的bug,所以目标状态就是n个0。对于每个补丁,会给出使用这个补丁的时间,另外会给出两个长度为n的字符串,第一个字符串表示这个补丁适用于什么情况下的bug,第二个字符串表示使用完这个补丁后原来的bug会变成怎么样。
思路
在任意时刻,每个bug可能存在也可能不存在,所以可以用一个n位二进制串表示当前软件的“状态”。打完补丁之后,bug状态会发生改变,对应状态转移。
这张图的节点就是对于每个BUG有没有修好所构成的2^n 个状态,至于边,就是某个状态和能通过补丁转移成的另一个状态间有一条单向边,而边权就是修复的时间

代码如下:

#include
using namespace std;
const int maxn=1<<20;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m;
int vis[maxn],d[maxn];

struct Path
{
    int time;
    string before,after;
}p[maxn];

struct node
{
    int bugs,dist;
    bool operator <(const node&rhs) const
    {
        return dist>rhs.dist;
    }

};

int dijkstra()
{
    memset(d,inf,sizeof(d));
    memset(vis,0,sizeof(vis));
    priority_queue<node>q;
    node start;
    start.bugs=(1<<n)-1;
    start.dist=0;
    d[start.bugs]=0;
    q.push(start);
    while(!q.empty())
    {
        node u=q.top();
        q.pop();
        if(u.bugs==0)
            return u.dist;
        if(vis[u.bugs])
            continue;
        vis[u.bugs]=1;
        for(int i=0;i<m;i++)
        {
            bool flag=true;
            for(int j=0;j<n;j++)
            {
                if(p[i].before[j]=='-'&&(u.bugs&(1<<j))) //x.bug & (1<
                {
                    flag=false;
                    break;
                }
                if(p[i].before[j]=='+'&&!(u.bugs&(1<<j)))
                {
                    flag=false;
                    break;
                }
            }
            if(!flag)
                continue;
            node v;
            v.bugs=u.bugs;
            for(int j=0;j<n;j++)
            {
                if(p[i].after[j]=='-')
                    v.bugs&=~(1<<j);//将v.bug的二进制位中的第j位置为0
                if(p[i].after[j]=='+')
                    v.bugs|=(1<<j);//将v.bug的二进制位中的第j位置为1
            }

            d[v.bugs]=min(d[v.bugs],u.dist+p[i].time);//d[v.bugs]=min(d[v.bugs],d[u.bugs]+p[i].time)
            v.dist=d[v.bugs];
            q.push(v);
        }
    }
    return -1;
}



int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int kase=0;
    while(cin>>n>>m&&n&&m)
    {
        for(int i=0;i<m;i++)
            cin>>p[i].time>>p[i].before>>p[i].after;
        int ans=dijkstra();
        cout<<"Product "<<++kase<<endl;
        if(ans<0)
            cout<<"Bugs cannot be fixed."<<endl<<endl;
        else
            cout<<"Fastest sequence takes "<<ans<<" seconds."<<endl<<endl;
    }
}

ps:果然,二进制还是要多了解了解,多学学。

你可能感兴趣的:(ACM刷题,算法)