Stay Hungry,Stay Foolish!

巧抓纪念币 -- BFS -- 剪枝优化

巧抓纪念币

http://go.helloworldroom.com:50080/problem/2723

题目描述

为了让同学们留下美好的回忆,博物院准备了很多纪念币,但需要通过特制的游戏手柄 抓取。纪念币在数轴的任意位置 Y。游戏手柄通过轨道移动,轨道与数轴同长且首尾对齐。 当游戏手柄的坐标与纪念币的坐标相同则抓取成功。若游戏手柄当下坐标为 X,下一次可以 移动到 X-1、X+1、2X 的位置,当然,这些位置不能超出轨道。 最终所有同学都抓到了纪念币。若已知 X 和 Y,如何移动最快呢?

输入格式

一行,包含两个整数 X,Y,表示游戏手柄和纪念币的初始位置。

输出格式

一行,包含一个数,表示游戏手柄最少需要移动的次数。

样例数据

input

5 17

output

4

样例说明:可行方案:5-->4-->8-->16-->17,共移动 4 次。

数据规模 对于 100%的数据,满足 X 和 Y 在数轴范围内。数轴长度为 100000。

 

BFS Intro

https://www.guru99.com/breadth-first-search-bfs-graph-example.html

宽度优先搜索算法,为图论中遍历图所有节点的一种算法。

从跟节点访问开始

然后访问 跟根节点有直接关联的 子节点 C (一级儿子),

然后访问 跟C所有节点有直接关联的 子节点 D (二级儿子),

......

 

What is Graph traversals?

A graph traversal is a commonly used methodology for locating the vertex position in the graph. It is an advanced search algorithm that can analyze the graph with speed and precision along with marking the sequence of the visited vertices. This process enables you to quickly visit each node in a graph without being locked in an infinite loop.

The architecture of BFS algorithm

  1. In the various levels of the data, you can mark any node as the starting or initial node to begin traversing. The BFS will visit the node and mark it as visited and places it in the queue.
  2. Now the BFS will visit the nearest and un-visited nodes and marks them. These values are also added to the queue. The queue works on the FIFO model.
  3. In a similar manner, the remaining nearest and un-visited nodes on the graph are analyzed marked and added to the queue. These items are deleted from the queue as receive and printed as the result.

 

算法步骤:

 

https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/

BFS算法,依赖一个队列数据结构。

// Program to print BFS traversal from a given
// source vertex. BFS(int s) traverses vertices
// reachable from s.
#include<bits/stdc++.h>
using namespace std;

// This class represents a directed graph using
// adjacency list representation
class Graph
{
    int V; // No. of vertices

    // Pointer to an array containing adjacency
    // lists
    vector<list<int>> adj;
public:
    Graph(int V); // Constructor

    // function to add an edge to graph
    void addEdge(int v, int w);

    // prints BFS traversal from a given source s
    void BFS(int s);
};

Graph::Graph(int V)
{
    this->V = V;
    adj.resize(V);
}

void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w); // Add w to v’s list.
}

void Graph::BFS(int s)
{
    // Mark all the vertices as not visited
    vector<bool> visited;
    visited.resize(V,false);

    // Create a queue for BFS
    list<int> queue;

    // Mark the current node as visited and enqueue it
    visited[s] = true;
    queue.push_back(s);

    while(!queue.empty())
    {
        // Dequeue a vertex from queue and print it
        s = queue.front();
        cout << s << " ";
        queue.pop_front();

        // Get all adjacent vertices of the dequeued
        // vertex s. If a adjacent has not been visited,
        // then mark it visited and enqueue it
        for (auto adjecent: adj[s])
        {
            if (!visited[adjecent])
            {
                visited[adjecent] = true;
                queue.push_back(adjecent);
            }
        }
    }
}

// Driver program to test methods of graph class
int main()
{
    // Create a graph given in the above diagram
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);

    cout << "Following is Breadth First Traversal "
        << "(starting from vertex 2) \n";
    g.BFS(2);

    return 0;
}

 

思路

 

Code

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
#include <limits.h>

/*
http://go.helloworldroom.com:50080/problem/2723
*/

class Node {
    public:
        int pos;
        int steps;

    public:
        Node(int _pos, int _steps) {
            pos = _pos;
            steps = _steps;
        }

        bool operator<(const Node &nd) const {
            if (steps < nd.steps) {
                return true;
            } else {
                return false;
            }
        }

        bool operator>(const Node &nd) const {
            if (steps > nd.steps) {
                return true;
            } else {
                return false;
            }
        }
};


int get_huristic_steps(int src, int dst) {
    int pos = src;
    int target = dst;

    if (pos == target) {
        return 0;
    }

    if (pos < target) {
        int times = 0;
        int low_bound = pos;
        int up_bound = 0;

        while (true) {
            up_bound = 2 * low_bound;
            times++;

            if (target >= low_bound && target <= up_bound) {
                break;
            }

            low_bound = up_bound;
        }

        int dist_low = target - low_bound;
        int dist_up = up_bound - target;
        int dist = min(dist_low, dist_up);

        return times + dist;
    }

    if (pos > target) {
        return target - pos;
    }

    return INT_MAX;
}

int bfs(int src, int dst) {
    // smallest on head
    priority_queue<Node, vector<Node>, greater<Node>> pq;
    set<int> closed;

    int limit = abs(src - dst);

    pq.push(Node(src, 0));

    while (!pq.empty()) {
        class Node nd = pq.top();
        pq.pop();

        int pos = nd.pos;
        int steps = nd.steps;

//        cout << "pos = " << pos << endl;
//        cout << "steps = " << steps << endl;

        if (pos == dst) {
//            cout << "found steps=" << steps << endl;
            return steps;
        }

        closed.insert(pos);

        if (closed.find(pos - 1) == closed.end() ) {
            if (steps + 1 <= limit) {
                pq.push(Node(pos - 1, steps + 1));
            }
        }

        if (closed.find(pos + 1) == closed.end()) {
            if (steps + 1 <= limit) {
                pq.push(Node(pos + 1, steps + 1));
            }
        }

        /*
        only if pos is in left of dst, then 2 * x can be one option
        */
        if (pos < dst) {
            if (closed.find(2 * pos) == closed.end()) {
                if (steps + 1 <= limit) {
                    pq.push(Node(pos * 2, steps + 1));
                }
            }
        }
    }
}


int main() {
    int x, y;

    cin >> x >> y;

    int ans = bfs(x, y);

    cout << ans << endl;

    return 0;
}

 

posted @ 2022-05-30 23:36  lightsong  阅读(138)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel