zoukankan      html  css  js  c++  java
  • [网络流24题] 软件补丁问题

    题目链接:戳我
    感觉虽然在所谓的网络流24题编制里,但是并没有看出来怎么用网络流做?(听说网络流24题全名不叫网络流24题???
    看到n的范围挺小的,我们考虑状压。
    转移的过程可以放到图论里面,因为要求费用最小,所以我们想到了最短路!(笑
    所以就是dij+状压转移嘛qwqwq(我就是不写spfa!!!
    注意一下非法情况的判断为f1里面包含,但是当前情况u不包含。或者f2里面不包含当前情况却包含了。
    转移的下一个状态v对于f1的修改情况,我们这里采用减法操作,但是一定要判断这一位上是否有1再减去!(有可能本来就没有这个漏洞,所以就不需要修补啊qwq)
    开始的情况为dis[(1<<n)-1],结束的情况为dis[0]。
    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int n,m,t,T;
    char cur1[21],cur2[21];
    struct Node
    {
        int u,d;
        friend bool operator <(struct Node x,struct Node y){return x.d>y.d;}
    };
    int head[1050000],dis[1050000],done[1050000],b1[110][21],b2[110][21],f1[110][21],f2[110][21],cost[110];
    inline bool check(int now,int x)
    {
        for(int i=0;i<n;i++)
        {
            if(b1[x][i]==1&&!(now&(1<<i))) return false;
            if(b2[x][i]==1&&(now&(1<<i))) return false;
        }
        return true;
    }
    inline void dij()
    {
        priority_queue<Node>q;
        memset(dis,0x3f,sizeof(dis));
        q.push((Node){T,0}),dis[T]=0;
        while(!q.empty())
        {
            int u=q.top().u; q.pop(); 
            if(done[u]) continue;
            done[u]=1;
            for(int i=1;i<=m;i++)
            {
                if(check(u,i)==false) continue;
                int v=u;
                for(int j=0;j<n;j++)
                {
                    if(f1[i][j]) v-=v&(1<<j);
                    if(f2[i][j]) v|=1<<j;   
                }
                if(dis[v]>dis[u]+cost[i])
                    dis[v]=dis[u]+cost[i],q.push((Node){v,dis[v]});
            }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        T=(1<<n)-1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%s%s",&cost[i],cur1,cur2);
            int len1=strlen(cur1),len2=strlen(cur2);
            for(int j=0;j<len1;j++)
            {
                if(cur1[j]=='+') b1[i][j]=1;
                if(cur1[j]=='-') b2[i][j]=1;
            }
            for(int j=0;j<len2;j++)
            {
                if(cur2[j]=='-') f1[i][j]=1;
                if(cur2[j]=='+') f2[i][j]=1;
            }
        }
        dij();
        printf("%d
    ",dis[0]==0x3f3f3f3f?0:dis[0]);
    }
    
  • 相关阅读:
    es6简述
    vue梳理
    webpack常用插件
    JS知识点
    CSS知识点
    224646
    223301
    图书馆 摘 1
    消息队列高手课 笔记6
    消息队列高手课 笔记5
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10291309.html
Copyright © 2011-2022 走看看