软件补丁问题

一道冒充网络流的最短路题。
根据题意,用位运算表示能否转移与转以后的状态。
(!((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]);
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9280168.html