POJ 2908 Quantum(BFS + 优先队列)

题意:

初始串经过一系列操作可以变换成目标串,每一次操作需要耗费一定的能量,求最小的能量。

思路:

1. 这一题同样采取 BFS 但是求的结果并不是最短路径,而是最小的耗能。其实也就是变换下思路,每次深搜之后把耗能最小的先出队列即可;

2. 这样的话可以把题目转换成优先队列的 dijstra 算法, 从源点到目标点的距离 -> 这里的点的变换即是状态的变换;

3. 题目中有个小 trick 使得一般的优先队列 BFS 算法无效,考虑如下 case:

   FFFF 10 , FFNN 1 , NNFF 1 , 0000 -> 1111 显然最小功耗是 2 而非 10,所以采用 dijstra 算法是合适的。

4. 由于题目中 L <= 20,所以在本题采用位运算会使过程变得十分优美,最终代码跑到了 141ms ;

 

 
  
#include <iostream>

#include <algorithm>

#include <queue>

using namespace std;



struct ST {

    int state, cost;

    ST(int _state, int _cost) : state(_state), cost(_cost) {}

    bool operator < (const ST& other) const { return cost > other.cost; }

};



struct OP {

    int op_and, op_or, op_xor;

    int cost;

} op[40];



const int INFS = 0x3fffffff;

int L, N, M, dis[1<<20];

bool vis[1<<20];



int bfs(int s, int t) {

    priority_queue<ST> Q;

    Q.push(ST(s, 0));



    for (int i = 0; i < 1<<L; i++)

        dis[i] = INFS, vis[i] = false;

    dis[s] = 0;



    while (!Q.empty()) {

        ST u = Q.top();

        Q.pop();



        if (u.state == t) 

            return u.cost;

        vis[s] = true;



        for (int i = 0; i < N; i++) {

            int v = u.state;

            v &= op[i].op_and;

            v |= op[i].op_or;

            v ^= op[i].op_xor;

            if (!vis[v] && dis[v] > u.cost + op[i].cost) {

                dis[v] = u.cost + op[i].cost;

                Q.push(ST(v, dis[v]));

            }

        }

    }

    return -1;

}



int main() {

    int cases;

    scanf("%d", &cases);

    while (cases--) {

        scanf("%d%d%d", &L, &N, &M);

        for (int i = 0; i < N; i++) {

            char s[30];

            scanf("%s%d", s, &op[i].cost);

            op[i].op_and = op[i].op_or = op[i].op_xor = 0;

            for (int j = 0; s[j]; j++) {

                op[i].op_and <<= 1;

                op[i].op_or <<= 1;

                op[i].op_xor <<= 1;

                if (s[j] == 'N') 

                    op[i].op_or |= 0;

                else if (s[j] == 'C') 

                    op[i].op_and |= 1;

                else if (s[j] == 'F')

                    op[i].op_xor |= 1;

                else if (s[j] == 'S')

                    op[i].op_or |= 1;

            }

            op[i].op_and = ~op[i].op_and;

        }

        for (int i = 0; i < M; i++) {

            char src[30], dst[30];

            int u = 0, v = 0;

            scanf("%s%s", src, dst);

            for (int j = 0; src[j]; j++)

                u <<= 1, u |= (src[j] - '0');

            for (int j = 0; dst[j]; j++)

                v <<= 1, v |= (dst[j] - '0');

            int ans = bfs(u, v);

            if (ans != -1) 

                printf("%d", ans);

            else 

                printf("NP");

            printf("%c", i == M-1 ? '\n' : ' ');

        }

    }

    return 0;

}
 

你可能感兴趣的:(quantum)