P2761 软件补丁问题

问题描述

某软件有\(n\)\(bug\) ,现有\(m\)种补丁,第\(i\)种补丁必须在有 \(B1[i]\)集合中的所有 \(bug\) 且没有\(B2[i]\)中任何一个 \(bug\) 时才能运行,效果是去除\(F1[i]\)集合中所有的 \(bug\) 但会新增\(F2[i]\) 集合中的所有bug,且会消耗\(T[i]\)的时间。求去除所有\(bug\)所需的最短时间,无解输出\(0\)

输入格式

\(1\) 行有 \(2\) 个正整数 \(n\)\(m,n\) 表示错误总数,\(m\) 表示补丁总数,\(1<=n<=20, 1<=m<=100\)

接下来 \(m\) 行给出了 \(m\) 个补丁的信息。每行包括一个运行补丁 \(i\) 所需的时间,以及 \(2\) 个长度为 \(n\) 的字符串,中间用一个空格符隔开。

\(1\) 个字符串中,如果第 \(k\) 个字符为“+”,则表示第 \(k\) 个错误属于 \(B1[i]\),若为“-”,则表示第 \(k\) 个错误属于 \(B2[i]\),若为“0”,则第 \(k\) 个错误既不属于 \(B1[i]\) 也不属于 \(B2[i]\) ,即不影响补丁 i 的使用。

\(1\) 个字符串中,如果第 \(k\) 个字符为“+”,则表示第 \(k\) 个错误属于 \(F1[i]\),若为“-”,则表示第 \(k\) 个错误属于 \(F2[i]\),若为“0”,则第 \(k\) 个错误既不属于 \(F1[i]\) 也不属于 \(F2[i]\) ,即不会受补丁 \(i\) 影响而改变。

第 2 个字符串中,如果第 k 个字符 bk为“-”,则表示第 k 个错误属于 F1[i],若为“+”,则表示第 k 个错误属于 F2[i],若为“0”,则第 k 个错误既不属于 F1[i]也不属于 F2[i],即软件中是否包含第 k 个错误不会因使用补丁i 而改变。

输出格式

输出总耗时数(最小)。如果问题无解,则输出 0。

解析

可以把现在\(bug\)的状态压缩。用\(SPFA\)(或者\(Dijkstra\))找最短路
把每个补丁的B1,B2,F1,F2压缩成二进制字符串,把状态放进队列里寻找最短路,用t[i]来表示到达状态i所需要的时间,如果最后状态为0所需要的时间为初始化的0x3f就输出0,否则输出t[0]
代码如下

#include <bits/stdc++.h>
#define N 1<<21
#define inf 0x7f
using namespace std;
int m,n;
int h1[N],h2[N],c1[N],c2[N];
int len[105];
char s;
int t[N];
bool vis[N];

void spfa(){
	memset(t,inf,sizeof(t));
	queue<int> q;
	t[(1<<n)-1]=0;q.push((1<<n)-1);
	while (!q.empty()){
		int top=q.front();q.pop();
		vis[top]=0;
		for (int i=1;i<=m;i++){
			if (((top&h1[i])==h1[i])&&((top&h2[i])==0)){
				int news=(((top|c1[i])^c1[i])|c2[i]);
				if (t[top]+len[i]<t[news]){
					t[news]=t[top]+len[i];
					if (!vis[news]){
						vis[news]=1;
						q.push(news);}}}}}}

int main(){
	scanf("%d%d",&n,&m);
	for (int l=1;l<=m;l++){
		scanf("%d",&len[l]);
		scanf("%1c",&s);
		for (int i=1;i<=n;i++){
			scanf("%1c",&s);
			if (s=='+')
				h1[l]|=(1<<(i-1));
			else if (s=='-')
				h2[l]|=(1<<(i-1));
		}
		scanf("%1c",&s);
		for (int i=1;i<=n;i++){
			scanf("%1c",&s);
			if (s=='+')
				c2[l]|=(1<<(i-1));
			else if (s=='-')
				c1[l]|=(1<<(i-1));
		}
	}
	spfa();
	if (t[0]==2139062143)	printf("0\n");//经过下载数据后输出的
	else printf("%d",t[0]);
	return 0;
}
posted @ 2021-09-08 12:00  hewt  阅读(36)  评论(0编辑  收藏  举报