软件补丁问题
题目描述
T 公司发现其研制的一个软件中有 n n n 个错误,随即为该软件发放了 m m m 个补丁程序。
每一个补丁程序都有其特定的适用环境,某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用。一个补丁在排除某些错误的同时,往往会加入另一些错误。
换句话说,对于任意一个补丁 i i i,都有四个与之相应的集合 B 1 i , B 2 i , F 1 i B1_i,B2_i,F1_i B1i,B2i,F1i 和 F 2 i F2_i F2i。仅当软件包含 B 1 i B1_i B1i 中的所有错误,而不包含 B 2 i B2_i B2i 中的任何错误时,才可以使用补丁 i i i。补丁 i i i 将修复软件中的某些错误集合 F 1 i F1_i F1i,而同时加入另一些错误 F 2 i F2_i F2i。另外,运行每个补丁都耗费一定的时间。
试设计一个算法,利用 T 公司提供的 m m m 个补丁程序将原软件修复成一个没有错误的软件,并使修复后的软件耗时最少。对于给定的 n n n 个错误和 m m m 个补丁程序,找到总耗时最少的软件修复方案。
输入格式
第一行有两个正整数 n n n 和 m m m。 n n n 表示错误总数, m m m表示补丁总数。
接下来 m m m 行给出了 m m m 个补丁的信息。每行包括一个正整数,表示运行补丁程序 i i i 所需时间,以及两个长度为 n n n 的字符串。中间用一个空格符隔开。
第一个字符串中,如果第
k
k
k 个字符为 +
,则表示第
k
k
k 个错误属于
B
1
i
B1_i
B1i。若为 -
,则表示第
k
k
k 个错误属于
B
2
i
B2_i
B2i。若为 0
,则第
k
k
k 个错误既不属于
B
1
i
B1_i
B1i 也不属于
B
2
i
B2_i
B2i,即软件中是否包含第
k
k
k 个错误并不影响补丁
i
i
i 的可用性。
第二个字符串中,如果第
k
k
k 个字符为 -
,则表示第
k
k
k 个错误属于
F
1
i
F1_i
F1i。若为 +
,则表示第
k
k
k 个错误属于
F
2
i
F2_i
F2i。若为 0
,则第
k
k
k 个错误既不属于
F
1
i
F1_i
F1i 也不属于
F
2
i
F2_i
F2i,即软件中是否包含第
k
k
k 个错误不会因使用补丁
i
i
i 而改变。
输出格式
程序运行结束时,将总耗时数输出。如果问题无解,则输出 0
。
样例 #1
样例输入 #1
3 3
1 000 00-
1 00- 0-+
2 0-- -++
样例输出 #1
8
提示
对于 100 % 100\% 100% 的数据: 1 ≤ n ≤ 20 1\le n\le 20 1≤n≤20, 1 ≤ m ≤ 100 1\le m\le 100 1≤m≤100。
题解
其实这道题可以把状态(剩余BUG的状压)看作一个点,然后用SPFA就行了,然后枚举边的时候只需要简单的判断一下就行了,没必要连边
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 21, maxm = 210;
int dp[1 << maxn];
int n, m;
int B1[maxm], B2[maxm], F1[maxm], F2[maxm];
int cost[maxm];
bool book[1 << maxn];
char ch[maxn + 10];
queue<int> que;
signed main(){
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++){
scanf("%d",&cost[i]);
scanf("%s",ch);
for(int j = 0;j < n;j++){
if(ch[j] == '+')
B1[i] |= (1 << j);
else if(ch[j] == '-')
B2[i] |= (1 << j);
}
scanf("%s",ch);
for(int j = 0;j < n;j++){
if(ch[j] == '-')
F1[i] |= (1 << j);
else if(ch[j] == '+')
F2[i] |= (1 << j);
}
}
memset(dp,0x3f,sizeof(dp)); dp[(1 << n) - 1] = 0;
que.push((1 << n) - 1); book[(1 << n) - 1] = true;
while(!que.empty()){
int sta = que.front();
for(int i = 1;i <= m;i++){
if((sta & B1[i]) == B1[i] && (sta & B2[i]) == 0){
int nsta = ((sta | F1[i]) | F2[i]) ^ F1[i];
if(dp[nsta] > dp[sta] + cost[i]){
dp[nsta] = dp[sta] + cost[i];
if(!book[nsta]){
que.push(nsta);
book[nsta] = true;
}
}
}
}
que.pop();book[sta] = false;
}
if(dp[0] == 0x3f3f3f3f)puts("0");
else printf("%d\n",dp[0]);
return 0;
}