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

29 篇文章 0 订阅
14 篇文章 0 订阅

UVA-658

题目:假定有n个潜在的bug和m个补丁,每个补丁用长为n的字符串表示。首先输入bug数目以及补丁数目。然后就是对m个补丁的描述,共有m行。每行首先是一个整数,表明打该补丁所需要的时间。然后是两个字符串,地一个字符串是对软件的描述,只有软件处于该状态下才能打该补丁该字符串的每一个位置代表bug状态(-代表该位置没bug,+代表该位置有bug,0表示该位置无论有没有bug都可打补丁)。然后第二个字符串是对打上补丁后软件状态的描述-代表该位置上的bug已经被修复,+表示该位置又引入了一个新的bug, 0表示该位置跟原来状态一样)。要求用最少时间完成对软件的修复,即将所有位置全都置为0。

思路:

        1️⃣当你看到这里时,我觉得你要先看一下 位运算 , 真的是一个特别高级的东东。

            位运算 相关知识

        2️⃣直接上代码,具体思路都在注释里。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<sstream>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
const int INF = 1000000000;

int vis[1<<21],d[1<<21];
int kase=0,len,n;
struct S{
    int time;
    char begin[21];
    char end[21];
}s[200];
struct Node{
    int bug;
    int time; //到开始结点所用时间
    bool operator < (const Node & a)const {
        return time>a.time;
    }
};
int Dijkstra(){
    for(int i = 0;i<(1<<len);i++){ //初始化
        vis[i] = 0;
        d[i] = INF;
    }
    priority_queue<Node> list; //用时少的状态优先出队
    Node start;
    start.bug = (1<<len)-1; //初始化开始状态,即将len位数全置为1,并将该二进制所表示的数作为该状态的编号
    start.time = 0;
    list.push(start);
    d[start.bug] = 0; //d[i]表示从开始结点到i号结点的最短用时
    while(!list.empty()){
        Node now = list.top();list.pop();
        if(now.bug==0) return now.time; //已到最终状态,则返回
        if(vis[now.bug]) continue; //vis[i]用于标记 状态i 是否已经出队访问过
        vis[now.bug] = 1;
        for(int i = 1;i<=n;i++){
            int check = 1;
            for(int j = 0;j<len;j++){
                if(s[i].begin[j]=='-'&&(now.bug & (1<<j))) {check = 0;break;} // (now.bug & (1<<j)) 指 取now.bug二进制的第j位取出(j从0开始)
                if(s[i].begin[j]=='+'&&!(now.bug & (1<<j))) {check = 0;break;}// !(now.bug & (1<<j)) 指 取now.bug二进制的第j位取出并取反(j从0开始)
            }
            if(!check) continue;
            Node next;
            next.time = s[i].time + now.time;
            next.bug = now.bug;
            for(int j = 0;j<len;j++){
                if(s[i].end[j]=='-') next.bug &= ~(1<<j); //把 next.bug 二进制的第j位取0
                if(s[i].end[j]=='+') next.bug |= (1<<j); //把next.bug 二进制的第j位取1
                //第j位为'0'则和now.bug的第j位保持一致
            }
            if(d[next.bug]>next.time){ //如果当前结点next.bug的时间大于当前的最优值d[next.bug],则d[i]更新,并进队
                d[next.bug] = next.time;
                list.push(next);
            }
        }
    }
    return -1;
}
int main(){
    while(scanf("%d%d",&len,&n)==2){
        if(len==0&&n==0) break;
        printf("Product %d\n",++kase);
        for(int i = 1;i<=n;i++) scanf("%d%s%s",&s[i].time,s[i].begin,s[i].end);
        int ans = Dijkstra();
        if(ans!=-1) printf("Fastest sequence takes %d seconds.\n\n",ans);
        else printf("Bugs cannot be fixed.\n\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值