【codevs 2218】补丁vs错误(CTSC 1999)

3 篇文章 0 订阅
3 篇文章 0 订阅

好容易看到一个年纪和我差不多的题,怀着激动的心情WA了好多遍……

题目描述

错误就是人们所说的Bug。用户在使用软件时总是希望其错误越少越好,最好是没有错误的。但是推出一个没有错误的软件几乎不可能,所以很多软件公司都在疯狂地发放补丁(有时这种补丁甚至是收费的)。T公司就是其中之一。

上个月,T公司推出了一个新的字处理软件,随后发放了一批补丁。最近T公司发现其发放的补丁有致命的问题,那就是一个补丁在排除某些错误的同时,往往会加入另一些错误.

此字处理软件中只可能出现n个特定的错误,这n个错误是由软件本身决定的。T公司目前共发放了m个补丁,对于每一个补丁, 都有特定的适用环境,某个补丁只有在当前软件中包含某些错误而同时又不包含另一些错误时才可以使用,如果它被使用,它将修复某些错误而同时加入某些错误。另外,使用每个补丁都要耗一定的时间(即补丁程序的运行时间)。

更准确地说明:

设此字处理软件中可能出现的n个错误为集合B={b1,b2,…,bn}中的元素,T公司目前共发放了m个补丁:p1,p2,…,pm。对于每一个补丁pi, 都有特定的适用环境,某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以用,为了说明清楚,设错误集合:Bi+、 Bi-, 当软件包含了Bi+中的所有错误, 而没有包含Bi-中的任何错误时,补丁Pi才可以被使用,否则不能使用,显然 Bi+、Bi-交集为空。补丁pi将修复某些错误而同时加入某些错误,设错误集合Fi-、Fi+,使用过补丁pi之后,Fi-中的任何错误都不会在软件中出现,而软件将包含Fi+中的所有错误, 同样Fi-、Fi+交集为空。另外,使用每个补丁都要耗一定的时间(即补丁程序的运行时间)。

现在T公司的问题很简单,其字处理软件的初始版本不幸地包含了集合B中的全部n个错误, 有没有可能通过使用这些补丁(任意顺序地使用,一个补丁可使用多次), 使此字处理软件成为一个没有错误的软件。如果可能,希望找到总耗时最少的方案。

另一个版本

你有一个有n个bug的程序,有m个补丁
使用补丁的条件:
软件包含所有b+,不包含所有b-
使用补丁的后果:
软件不含所有f-,增加所有f+

样例

3 3
1 000 00-
1 00- 0-+
2 0-- -++

输出

8

样例解释

谁知到怎么出来的

操作

对于一个软件u
需要满足的条件

(u & b1 == b1) && !(u & b2)

使用后

    int v = u
    v |= f1
    v &= ~f2

位运算的世界
总而言之就是这样了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 1000 + 5;
const int LOG = 1 << (20 + 1);
struct modification
{
    int b1,b2;
    int f1,f2;
    int t;
}mod[MAXN];
int n,m;
queue <int> q;
int dis[LOG];
bool use[LOG];
void bfs(int s)
{
    memset(dis,0x3f,sizeof(dis));
    memset(use,0,sizeof(use));
    q.push(s);
    dis[s] = 0;
    use[s] = true;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        use[u] = false;
        for(int i = 1;i <= m;i ++)
        {
            if(((u & mod[i].b1) == mod[i].b1) && !(u & mod[i].b2))
            {
                int v = u;
                v |= mod[i].f1;
                v &= ~mod[i].f2;
                if(dis[v] > dis[u] + mod[i].t)
                {
                    dis[v] = dis[u] + mod[i].t;
                    if(!use[v])
                        q.push(v);
                    use[v] = true;
                }
            }
        }
    }
    return;
}
char b[MAXN],f[MAXN];
int l;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= m;i ++)
    {
        scanf("%d %s %s",&mod[i].t,b,f);
        for(int j = 0;j < n;j ++)
        {
            if(b[j] == '+')
                mod[i].b1 |= 1 << j;
            if(b[j] == '-')
                mod[i].b2 |= 1 << j;
        }
        for(int j = 0;j < n;j ++)
        {
            if(f[j] == '+')
                mod[i].f1 |= 1 << j;
            if(f[j] == '-')
                mod[i].f2 |= 1 << j;
        }
    }
    bfs((1 << n) - 1);
    printf("%d\n",dis[0] > 1000000 ? 0 : dis[0]);
    return 0;
}

FareStrom:“傻x题,一眼题,水题……”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值