luogu2761 软件补丁问题 状态压缩最短路径

关键词:状态压缩 最短路径

想不出快速办法,就先考虑考虑暴力。枚举每一种错误分布的情况,然后通过可用的补丁转化为另多种情况,这些情况又转化为更多种情况……我们可以用图来表示这种关系!

状态压缩:每个错误的状态可以压缩在一个整数里。

最短路径:如果一个状态可以用补丁变为另一种状态,则两个状态间连一条边,权值为补丁所需时间。

 

注意:二进制运算符,如&,|等,优先级比==低。所以有二进制运算时,等号左边记得要加括号。

#include <cstdio>
#include <cstring>
#include <cassert>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

#define LOOP(i, n) for(int i=0; i<n; i++)
const int MAX_STATE = 1 << 21, INF = 0x3f3f3f3f, MAX_BUG = 25, MAX_PATCH = 110;
int TotBug, TotPatch;
int HaveBug[MAX_PATCH], Normal[MAX_PATCH], Repair[MAX_PATCH], Add[MAX_PATCH];
int W[MAX_PATCH];

struct Node;
struct Edge;

struct Node
{
    Edge *Head;
    int Dist, State;
    bool Inq;
    Node() :Dist(INF){}
}_nodes[MAX_STATE];struct Edge
{
    Node *To;
    Edge *Next;
    int Weight;
    Edge(Node *to, Edge *next, int weight)
        :To(to),Next(next),Weight(weight){}
};
vector<Edge*> _edges;

void AddEdge(int uId, int vId, int weight)
{
    Node *from = uId + _nodes, *to = vId + _nodes;
    from->State = uId;
    to->State = vId;
    Edge *e = new Edge(to,from->Head,weight);
    _edges.push_back(e);
    from->Head = e;
}

void Build(Node *cur)
{
    LOOP(patch, TotPatch)
    {
        if (((cur->State & HaveBug[patch]) == HaveBug[patch]) && ((~cur->State) & Normal[patch]) == Normal[patch])
        {
            int newState = ((~Repair[patch])&cur->State) | Add[patch];
            if (cur->State != newState)
                AddEdge(cur->State, ((~Repair[patch])&cur->State) | Add[patch], W[patch]);
        }
    }
}

void SPFA()
{
    static queue<Node*> q;
    int curState = (1 << TotBug) - 1;
    Node *cur = curState + _nodes;
    cur->State = curState;
    cur->Dist = 0;
    Build(cur);
    cur->Inq = true;
    q.push(cur);
    while (!q.empty())
    {
        cur = q.front();
        q.pop();
        if (cur->Inq)
            cur->Inq = false;
        for (Edge *e = cur->Head; e; e = e->Next)
        {
            if (cur->Dist + e->Weight < e->To->Dist)
            {
                if (e->To->Dist == INF)
                    Build(e->To);
                e->To->Dist = cur->Dist + e->Weight;    
                if (!e->To->Inq)
                {
                    e->To->Inq = true;
                    q.push(e->To);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d", &TotBug, &TotPatch);
    char b[100], f[100];
    LOOP(patch, TotPatch)
    {
        scanf("%d %s %s", &W[patch], b, f);
        LOOP(bug, TotBug)
        {
            if (b[bug] == '+')
                HaveBug[patch] |= (1 << bug);
            else if (b[bug] == '-')
                Normal[patch] |= (1 << bug);
            if (f[bug] == '+')
                Add[patch] |= (1 << bug);
            else if (f[bug] == '-')
                Repair[patch] |= (1 << bug);
        }
    }
    SPFA();
    printf("%d\n", _nodes[0].Dist == INF ? 0 : _nodes[0].Dist);
    return 0;
}

 

posted @ 2018-02-13 22:50  headboy2002  阅读(141)  评论(0编辑  收藏  举报