[网络流24题] 洛谷P2761 软件补丁问题

题意:某公司发现其研制的一个软件中有 n个错误,随即为该软件发放了一批共 m 个补丁程序。对于每一个补丁 i ,都有 2 个与之相应的错误集合 B1(i)和 B2(i),使得仅当软件包含 B1(i)中的所有错误,而不包含 B2(i)中的任何错误时,才可以使用补丁 i。补丁 i 将修复软件中的某些错误 F1(i),而同时加入另一些错误 F2(i)。另外,每个补丁都耗费一定的时间。 试设计一个算法,利用公司提供的 m 个补丁程序将原软件修复成一个没有错误的软件,并使修复后的软件耗时最少。 

虽然是网络流24题,但是这题好像应该用最短路来做。

把20个bug状态压缩成二进制表示,然后跑Dijkstra最短路即可。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=110;
const int INF=0x3f3f3f3f;
int n,m;
struct bug{
    int tim;
    char p[22],q[22];
}a[N];

bool check(int now,int k) {
    for (int i=0;i<m;i++)
        if (a[k].p[i]=='+' && !(now&(1<<i)) || a[k].p[i]=='-' && (now&(1<<i))) return 0;
    return 1;    
}

int change(int now,int k) {
    for (int i=0;i<m;i++) {
        if (a[k].q[i]=='-') now=now&(~(1<<i));
        if (a[k].q[i]=='+') now=now|(1<<i);
    }
    return now;
}

int d[1<<22];
priority_queue<pii> q;
int Dijkstra() {
    memset(d,0x3f,sizeof(d));
    d[(1<<m)-1]=0;
    q.push(make_pair(0,(1<<m)-1));
    while (!q.empty()) {
        pii x=q.top(); q.pop();
        if (d[x.second]!=-x.first) continue;
        for (int i=1;i<=n;i++)
            if (check(x.second,i)) {
                int y=change(x.second,i);
                if (d[x.second]+a[i].tim<d[y]) {
                    d[y]=d[x.second]+a[i].tim;
                    q.push(make_pair(-d[y],y));
                }
            }
    }
    return d[0]==INF ? 0 : d[0];
}

int main()
{
    scanf("%d%d",&m,&n);
    for (int i=1;i<=n;i++) scanf("%d%s%s",&a[i].tim,&a[i].p,&a[i].q);
    
    cout<<Dijkstra()<<endl;
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/clno1/p/10709254.html