题意
一开始有一个软件有n个bug,然后开发商整了m个补丁。
对于每一个补丁都有四个集合b1,b2,f1,f2和一个整数cost组成。
对于对于当前软件能够使用一个补丁当且仅当,
b1集合里的所有bug都出现在当前软件内,b2集合中的所有bug都不出现在当前软件内。
这个时候使用补丁的效果就是
如果f1中的bug出现在当前软件内,那么这个bug被修复。同时f2的所有bug都出现在软件内。
求最小花费使得软件不存在bug
n<=20 m<=100
分析
看起来非常的像状压。但是实际上似乎就是状压
所以放在网络流24题里是什么意思呢…还是我姿势水平不对?
然后就考虑n非常小,所以状压表示。
然后这里建边显然是不合理的所以对于每个点都需要扫一遍看这条边能不能连出去。然后转移就好了。
反正没有负权用dijkstra稳的一批。
然后就没了。
code
#include<bits/stdc++.h>
using namespace std;
void read(int &x){
x=0; char c=getchar();
for (;c<48;c=getchar());
for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
#define pii pair<int,int>
#define A first
#define B second
#define mp make_pair
priority_queue< pii >Q;
int dis[1<<20],m;
bool vis[1<<20];
struct node{
int b1,b2,f1,f2,cost;
bool chk(int x){
return ((x&b1)==b1)&&((x&b2)==0);
}
int cl(int x){
x^=x&f1;
x|=f2;
return x;
}
}a[105];
void dijkstra(int x){
memset(vis,0,sizeof(vis));
memset(dis,63,sizeof(dis));
dis[x]=0; Q.push(mp(0,x));
for (;!Q.empty();){
x=Q.top().B; Q.pop();
if (vis[x])continue;
vis[x]=1;
if (x==0)return;
for (int i=1;i<=m;i++)if (a[i].chk(x)){
int to=a[i].cl(x);
if (dis[x]+a[i].cost<dis[to]){
dis[to]=dis[x]+a[i].cost;
Q.push(mp(-dis[to],to));
}
}
}
}
char s1[50],s2[50];
int main(){
// freopen("LOJ6009.in","r",stdin);
int n;
read(n); read(m);
int cost,tmp=(1<<n)-1,f1,f2,b1,b2;
for (int i=1;i<=m;i++){
read(cost);
scanf("%s",s1); scanf("%s",s2);
f1=f2=b1=b2=0;
for (int j=0;j<n;j++){
if (s1[j]=='+')b1|=1<<j;
if (s1[j]=='-')b2|=1<<j;
if (s2[j]=='-')f1|=1<<j;
if (s2[j]=='+')f2|=1<<j;
}
a[i]=(node){b1,b2,f1,f2,cost};
}
dijkstra(tmp);
if (!vis[0])printf("0\n");
else printf("%d\n",dis[0]);
return 0;
}
总结
总之想到什么就先大胆的瞎写吧…这样。