题意
软件有n(n<=20)个bug,m个补丁,补丁花费t时间,在一些bug存在的情况下解决部分bug并引入新的bug,求解决所有bug的最小时间花费
思路
状压,然后做最短路时判断打补丁的合法性即可
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n,m,dis[1<<22];
queue<int>q;int vis[1<<22];
int f1[1000],f2[1000],b1[1000],b2[1000],w[1000];
const int inf=(1<<30)-1;
void spfa(int s){
for(int i=0;i<(1<<n)-1;++i)dis[i]=inf;
dis[s]=0;
q.push(s);
while(!q.empty()){
int x=q.front();
vis[x]=0;
q.pop();
for(int i=0;i<m;++i)
if((x&b1[i])==b1[i]&&(x&b2[i])==0){
int y=((x|f1[i])|f2[i])^f1[i];
if(dis[x]+w[i]<dis[y]){
dis[y]=dis[x]+w[i];
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}
}
}
}
char c;
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i){
scanf("%d",&w[i]);
c=getchar();
for(int j=1;j<=n;++j){
c=getchar();
if(c=='+')b1[i]|=(1<<j-1);
if(c=='-')b2[i]|=(1<<j-1);
}
c=getchar();
for(int j=1;j<=n;++j){
c=getchar();
if(c=='+')f2[i]|=(1<<j-1);
if(c=='-')f1[i]|=(1<<j-1);
}
c=getchar();
}
spfa((1<<n)-1);
if(dis[0]==inf)printf("0");
else printf("%d",dis[0]);
return 0;
}