软件补丁问题

一道冒充网络流的最短路题。
根据题意,用位运算表示能否转移与转以后的状态。
!(\(u\)&\(cantinc\)[i]))&&(!(\(incw\)[i]&\(u\) ^ \(incw\)[i])
\(u\)表示旧状态,\(cantinc\)(can't include),\(inc\)(include wrong)
如果旧状态不包含can't include 的,而且包括全部需要include的,那么就可以转移。
\(now\)=(\(u\)^ (\(u\)&\(fixx\)[i]))|\(neww\)[i]
\(now\)表示新状态,\(fixx\)表示修复的,\(neww\)表示新弄出来的漏洞,转移即可。

但有一个坑点,空间根本开不下Orz
但是考虑到数据小,可以边spfa,直接暴力枚举。也算开了个新思路。
Tip:不要在main函数不打spfa,开始怀疑spfa函数写错Orz

#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,t[125];
char w[125][25],r[125][25];
int fixx[125],neww[125],incw[125],cantinc[125],dis[1<<20];
bool inq[1<<20];
void spfa() {
    queue<int>q;
    memset(dis,0x3f,sizeof dis);
    dis[(1<<n)-1]=0;
    q.push((1<<n)-1);
    inq[(1<<n)-1]=1;
    while(!q.empty()) {
        int u=q.front();
        q.pop(),inq[u]=0;
        for(int i=1; i<=m; i++) {
            int now=(u^(u&fixx[i]))|neww[i];
            if((!(u&cantinc[i]))&&(!(incw[i]&u^incw[i]))) {
                if(dis[u]+t[i]<dis[now]) {
                    dis[now]=dis[u]+t[i];
                    if(!inq[now]) {
                        q.push(now);
                        inq[now]=1;
                    }
                }
            }
        }
    }
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++) scanf("%d%s%s",&t[i],w[i],r[i]);
    for(int i=1; i<=m; i++) {
        for(int j=0; j<n; j++) {
            if(w[i][j]=='-') cantinc[i]|=(1<<j);
            else if(w[i][j]=='+') incw[i]|=(1<<j);
        }
        for(int j=0; j<n; j++) {
            if(r[i][j]=='-') fixx[i]|=(1<<j);
            else if(r[i][j]=='+') neww[i]|=(1<<j);
        }
    }
    spfa();
    printf("%d",dis[0]==0x3f3f3f3f?0:dis[0]);
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9280168.html
今日推荐