zoukankan      html  css  js  c++  java
  • 密码锁

    二次联通门 : 密码锁

    然而是假的联通门。。。

    题目描述

    hzwer有一把密码锁,由N个开关组成。一开始的时候,所有开关都是关上的。当且仅当开关x1,x2,x3,…xk为开,其他开关为关时,密码锁才会打开。
    他可以进行M种的操作,每种操作有一个size[i],表示,假如他选择了第i种的操作的话,他可以任意选择连续的size[i]个格子,把它们全部取反。(注意,由于黄金大神非常的神,所以操作次数可以无限>_<)
    本来这是一个无关紧要的问题,但是,黄金大神不小心他的钱丢进去了,没有的钱他哪里能逃过被chenzeyu97 NTR的命运?>_< 于是,他为了虐爆czy,也为了去泡更多的妹子,决定打开这把锁。但是他那么神的人根本不屑这种”水题”。于是,他找到了你。
    你的任务很简单,求出最少需要多少步才能打开密码锁,或者如果无解的话,请输出-1。

    输入

    第1行,三个正整数N,K,M,如题目所述。
    第2行,K个正整数,表示开关x1,x2,x3..xk必须为开,保证x两两不同。
    第三行,M个正整数,表示size[i],size[]可能有重复元素。

    输出

    输出答案,无解输出-1。

    样例输入

    10 8 2 1 2 3 5 6 7 8 9 3 5

    样例输出

    2

    提示

    【样例输入2】
    3 2 1
    1 2
    3
    【样例输出2】
    -1
    【数据规模】
    对于50%的数据,1≤N≤20,1≤k≤5,1≤m≤3;
    对于另外20%的数据,1≤N≤10000,1≤k≤5,1≤m≤30;
    对于100%的数据,1≤N≤10000,1≤k≤10,1≤m≤100。
     
     
     
    /*
        将每个点拆成俩个点x,x’,能匹配的点xy从x向y’
        连边权值为1费用    Dist[i][j],源点向x连边,x’向汇连边,都是权值1    费用0,然后一遍    最小费用最大流就可以出解
        复制的hzwer的思路。。。
      90分
    */
    #include <cstring>
    #include <cstdio>
    #include <queue>
    
    #define Max 10005
    #define INF 1e8
    
    namespace Z 
    {
        void read (int &now)
        {
            now = 0;
            register char word = getchar ();
            while (word < '0' || word > '9')
                word = getchar ();
            while (word >= '0' && word <= '9')
            {
                now = now * 10 + word - '0';
                word = getchar ();
            }
        }
        
        inline int min (const int &_Qos_swc, const int &_Cos_ses)
        {
            return _Qos_swc < _Cos_ses ? _Qos_swc : _Cos_ses;
        }
    }
    
    int S, T = 45;
    int M, N, K;
    int key[Max];
    int size[Max];
    int Answer;
    int Count;
    
    int date[Max];
    int number[Max];
    
    int cost[Max / 100][Max / 100];
    
    bool visit[Max];
    int dis[Max];
    
    void Bfs (int res)
    {
        memset (visit, false, sizeof (visit));
        std :: queue <int> Queue;
        visit[res] = true;
        dis[res] = 0;
        Queue.push (res);
        int now;
        while (!Queue.empty ())
        {
            now = Queue.front ();
            Queue.pop ();
            for (int i = 1; i <= M; i++)
            {
                if (now + size[i] <= N && (!visit[size[i] + now]))
                {
                    visit[size[i] + now] = true;
                    dis[now + size[i]] = dis[now] + 1;
                    Queue.push (now + size[i]);
                }
                if (now - size[i] > 0 && (!visit[now - size[i]]))
                {
                    visit[now - size[i]] = true;
                    dis[now - size[i]] = dis[now] + 1;
                    Queue.push (now - size[i]);
                }
            }
        }
    }
    
    class Net_Flow_Type
    {
        private : 
        
            struct Edge_Date
            {
                int from;
                int to;
                int flow;
                int next;
                int cost;
            }
            edge[Max << 2];
            
            int Edge_Count;
            int edge_list[Max];
            int deep[Max];
            int pre[Max];
            
        public :
            
            void Prepare ()
            {
                Edge_Count = 1;
            }
            
            inline void AddEdge (int from, int to, int flow, int cost)
            {
                Edge_Count++;
                edge[Edge_Count].from = from;
                edge[Edge_Count].to = to;
                edge[Edge_Count].flow = flow;
                edge[Edge_Count].cost = cost;
                edge[Edge_Count].next = edge_list[from];
                edge_list[from] = Edge_Count;
                Edge_Count++;
                edge[Edge_Count].from = to;
                edge[Edge_Count].to = from;
                edge[Edge_Count].flow = 0;
                edge[Edge_Count].cost = -cost;
                edge[Edge_Count].next = edge_list[to];
                edge_list[to] = Edge_Count;
            }
            
            bool Spfa ()
            {
                for (int i = 0; i <= T; i++)
                    deep[i] = INF;
                std :: queue <int> Queue;
                memset (visit, false, sizeof visit);
                Queue.push (S);
                deep[S] = 0;
                visit[S] = true;
                int now;
                while (!Queue.empty ())
                {
                    now = Queue.front ();
                    Queue.pop ();
                    for (int i = edge_list[now]; i; i = edge[i].next)
                        if (edge[i].flow && deep[now] + edge[i].cost < deep[edge[i].to])
                        {
                            deep[edge[i].to] = deep[now] + edge[i].cost;
                            pre[edge[i].to] = i;
                            if (!visit[edge[i].to])
                            {
                                visit[edge[i].to] = true;
                                Queue.push (edge[i].to);
                            }
                        }
                    visit[now] = false;
                }
                return deep[T] < INF;
            }
            
            void Dinic ()
            {
                while (Spfa ())
                {
                    int res = INF;
                    for (int i = pre[T]; i; i = pre[edge[i].from])
                        res = Z :: min (res, edge[i].flow);
                    for (int i = pre[T]; i; i = pre[edge[i].from])
                    {
                        edge[i].flow -= res;
                        edge[i ^ 1].flow += res;
                        Answer += edge[i].cost * res;
                    }
                }
            }
            
            void Insert_Edges ()
            {
                int o = 0;
                for (int i = 1; i <= Count; i++)
                {
                    AddEdge (S, i, 1, 0);
                    AddEdge (i + Count, T, 1, 0); 
                }
                for (int i = 1; i <= Count; i++)
                    for (int j = 1; j <= Count; j++)
                        if (i != j && cost[i][j] != INF)
                            AddEdge (i, j + Count, 1, cost[i][j]);
            }
        
    };
    
    
    Net_Flow_Type Make;
    
    int main (int argc, char *argv[])
    {
        freopen ("password.in", "r", stdin);
        freopen ("password.out", "w", stdout);
        Z :: read (N);
        Z :: read (K);
        Z :: read (M);
        N++;
        Make.Prepare (); 
        for (int i = 1; i <= K; i++)
        {
            Z :: read (key[i]);
            date[key[i]] = 1;
        }
        for (int i = 1; i <= M; i++)
            Z :: read (size[i]);
        for (int i = N; i; i--)
            date[i] ^= date[i - 1];
        for (int i = 1; i <= N; i++)
            if (date[i])
                number[i] = ++Count;
        for (int i = 1; i <= N; i++)
            if (date[i])
            {
                Bfs (i); 
                for (int j = 1; j <= N; j++)
                {
                    if (!number[j])
                        continue;
                    if (!visit[j])
                        cost[number[i]][number[j]] = INF;
                    else
                        cost[number[i]][number[j]] = dis[j];
                }
            }
        Make.Insert_Edges (); 
        Make.Dinic ();
        printf ("%d", (Answer >> 1)); 
        return 0;
    }
  • 相关阅读:
    lucene入门
    ssm框架整合
    springmvc异常处理器和拦截器
    软件测试的策略是什么?
    软件质量保证体系是什么 国家标准中与质量保证管理相关的几个标准是什么?他们的编号和全称是什么?
    • β测试
    • α测试
    • 白盒测试
    黑盒测试
    • 数据库的兼容性
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6910149.html
Copyright © 2011-2022 走看看