您的位置:首页 > 理论基础 > 计算机网络

【网络流24题----12】软件补丁问题

2017-01-23 11:23 309 查看

软件补丁问题

Description

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

对于给定的 n 个错误和 m 个补丁程序,找到总耗时最少的软件修复方案。

Input

第 1 行有 2 个正整数 n 和 m,n 表示错误总数,m 表示补丁总数,1<=n<=20,1<=m<=100。
接下来 m 行给出了 m 个补丁的信息。
每行包括一个正整数,表示运行补丁程序 i 所需时间,以及 2 个长度为 n 的字符串,中间用一个空格符隔开。
第 1 个字符串中,如果第 k 个字符 bk 为“+” ,则表示第 k 个错误属于 B1[i],若为“-”,则表示第 k 个错误属于 B2[i],若为“0” ,则第 k 个错误既不属于 B1[i] 也不属于 B2[i],即软件中是否包含第 k 个错误并不影响补丁 i 的可用性。
第 2 个字符串中,如果第 k 个字符 bk 为“-”1 ,则表示第 k 个错误属于 F1[i],若为“+”,则表示第 k 个错误属于 F2[i],若为“0” ,则第 k 个错误既不属于 F1[i] 也不属于 F2[i],即软件中是否包含第 k 个错误不会因使用补丁 i 而改变。

Output

将总耗时数输出。如果问题无解,则输出 0。

Sample Input


3 3
1 000 00-
1 00- 0-+
2 0– -++



Sample Output


8



24题中的最后一个分层图最短路了,注意一下就是有的OJ上题目有误(f1,f2搞反了)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 110
#define SIZE 2000000
#define inf (llg)1e16
#define llg long long
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,tail,head,dl[SIZE+10],dis[(1<<20)+10],bj[(1<<20)+10];
char s[maxn];

struct node
{
llg dis,b1,b2,f1,f2;
}a[maxn];

void init()
{
cin>>n>>m;
for (llg i=0;i<(1<<n)-1;i++) dis[i]=inf;
for (llg i=1;i<=m;i++)
{
scanf("%lld",&a[i].dis);
scanf("%s",s);
for (llg k=0;k<n;k++)
{
if (s[k]=='+') a[i].b1+=(1<<k);
if (s[k]=='-') a[i].b2+=(1<<k);
}
scanf("%s",s);
for (llg k=0;k<n;k++)
{
if (s[k]=='-') a[i].f1+=(1<<k);
if (s[k]=='+') a[i].f2+=(1<<k);
}
}
tail=1; head=0; dl[1]=(1<<n)-1;
}

void spfa()
{
llg x,v;
do
{
head%=SIZE; head++;
x=dl[head]; bj[x]=0;
for (llg i=1;i<=m;i++)
if (((x|a[i].b1)==x) && ((x&a[i].b2)==0))
{
v=x;
for (llg k=0;k<n;k++) if ((v&(1<<k)) && (a[i].f1&(1<<k))) v^=(1<<k);
v|=a[i].f2;
if (dis[v]>dis[x]+a[i].dis)
{
dis[v]=dis[x]+a[i].dis;
if (!bj[v])
{
bj[v]=1;
tail%=SIZE; tail++;
dl[tail]=v;
}
}
}
}while (head!=tail);
}

int main()
{
yyj("a");
init();
spfa();
if (dis[0]==inf) cout<<0;else cout<<dis[0];
return 0;
}


软件补丁问题

Description

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

对于给定的 n 个错误和 m 个补丁程序,找到总耗时最少的软件修复方案。

Input

第 1 行有 2 个正整数 n 和 m,n 表示错误总数,m 表示补丁总数,1<=n<=20,1<=m<=100。
接下来 m 行给出了 m 个补丁的信息。
每行包括一个正整数,表示运行补丁程序 i 所需时间,以及 2 个长度为 n 的字符串,中间用一个空格符隔开。
第 1 个字符串中,如果第 k 个字符 bk 为“+” ,则表示第 k 个错误属于 B1[i],若为“-”,则表示第 k 个错误属于 B2[i],若为“0” ,则第 k 个错误既不属于 B1[i] 也不属于 B2[i],即软件中是否包含第 k 个错误并不影响补丁 i 的可用性。
第 2 个字符串中,如果第 k 个字符 bk 为“-”1 ,则表示第 k 个错误属于 F1[i],若为“+”,则表示第 k 个错误属于 F2[i],若为“0” ,则第 k 个错误既不属于 F1[i] 也不属于 F2[i],即软件中是否包含第 k 个错误不会因使用补丁 i 而改变。

Output

将总耗时数输出。如果问题无解,则输出 0。

Sample Input


3 3
1 000 00-
1 00- 0-+
2 0– -++



Sample Output


8

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: