zoukankan      html  css  js  c++  java
  • 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;
    }
     
  • 相关阅读:
    Mysql数据库--自学笔记--2
    Mysql数据库--自学笔记--1
    Python--作业3--模拟ATM程序的流程
    Python--数据存储:json模块的使用讲解
    如果我能成功,你也能
    有意注意到底有多重要
    没有人喜欢听废话——讲重点
    回顾你的一天是多么的重要
    思考的力量
    多问为什么,肯定不会错
  • 原文地址:https://www.cnblogs.com/kedebug/p/2986503.html
Copyright © 2011-2022 走看看