啊咧……这题不是网络流二十四题么……为啥是个状压dp……
把每一个漏洞看成一个状态,直接硬上状压dp
然后因为有后效型,得用spfa
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<queue> 5 #include<cstring> 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 const int N=25,M=105; 9 int n,m,tim[M],dp[1<<(N-2)],vis[1<<(N-2)],have[M],nhave[M]; 10 int disap[M],appea[M],a[M]; 11 char s1[N],s2[N];queue<int> q; 12 void init(int x){ 13 for(int i=n-1;~i;--i){ 14 switch(s1[i]){ 15 case '+':have[x]|=1<<i;break; 16 case '-':nhave[x]|=1<<i;break; 17 } 18 switch(s2[i]){ 19 case '+':appea[x]|=1<<i;break; 20 case '-':disap[x]|=1<<i;break; 21 } 22 } 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=m;++i){ 27 scanf("%d%s%s",&a[i],s1,s2); 28 init(i); 29 } 30 memset(dp,0x3f,sizeof(dp)); 31 dp[(1<<n)-1]=0,vis[(1<<n)-1]=1; 32 q.push((1<<n)-1); 33 while(!q.empty()){ 34 int u=q.front();q.pop(); 35 vis[u]=0; 36 for(int i=1;i<=m;++i){ 37 if((nhave[i]&(~u))!=nhave[i]) continue; 38 if((have[i]&u)!=have[i]) continue; 39 int to=(u&(~disap[i]))|appea[i]; 40 if(dp[to]>dp[u]+a[i]){ 41 dp[to]=dp[u]+a[i]; 42 if(!vis[to]){ 43 vis[to]=1,q.push(to); 44 } 45 } 46 } 47 } 48 printf("%d ",dp[0]==inf?0:dp[0]); 49 return 0; 50 }