A*

A*

179. 八数码

![在这里插入图片描述]( https://img-blog.csdnimg.cn/48ced096989c427bb9848d52796be168.png?x-oss-process=image/watermark ,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAUGFuc2XCtw==,size_20,color_FFFFFF,t_70,g_se,x_16)
样例输入:

2  3  4  1  5  x  7  6  8 

样例输出:

ullddrurdllurdruldr

代码模板:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>

#define x first
#define y second

using namespace std;

typedef pair<int, string> PIS;

//启发函数: 当前位置的数到正确位置的曼哈顿距离
int f(string state)
{
    int res = 0;
    for (int i = 0; i < 9; i ++ )
        if (state[i] != 'x')
        {
            int v = state[i] - '1';
            res += abs(v / 3 - i / 3) + abs(v % 3 - i % 3);
        }

    return res;
}

string bfs(string start)
{
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
    char op[5] = "urdl";

    string end = "12345678x";  //正确位置
    unordered_map<string, int> dist;
    unordered_map<string, pair<char, string>> pre; //记录路径
    //小根堆:当前实际距离 + 当前位置的估计距离 杭电oj的八数码给忘了记一下
    priority_queue<PIS, vector<PIS>, greater<PIS>> heap;

    heap.push({f(start), start});
    dist[start] = 0;

    while(heap.size())
    {
        auto t = heap.top();
        heap.pop();

        string state = t.y;
        if (state == end) break;
        
        //找x的位置
        int x, y;
        for (int i = 0; i < 9; i ++ )
            if (state[i] == 'x')
            {
                x = i / 3, y = i % 3;
                break;
            }
        
        string source = state;
        for (int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i], b = y + dy[i];
            if (a < 0 || a >= 3 || b < 0 || b >= 3) continue;
            state = source;
            swap(state[x * 3 + y], state[a * 3 + b]);
            if (dist.count(state) == 0 || dist[state] > dist[source] + 1)
            {
                dist[state] = dist[source] + 1;
                pre[state] = {op[i], source};
                heap.push({dist[state] + f(state), state}); //这里是当前真实距离 + 估计距离
            }
        }
    }

    string res;
    while (end != start)
    {
        res += pre[end].x;
        end = pre[end].y;
    }
    reverse(res.begin(), res.end());//

    return res;
}

int main()
{
    string start, seq;
    char c;
    while (cin >> c)
    {
        start += c;
        if (c != 'x') seq += c;
    }

    int cnt = 0;
    for (int i = 0; i < 8; i ++ )
        for (int j = i + 1; j < 8; j ++ )
            if (seq[i] > seq[j])
                cnt ++ ;

    if (cnt % 2) puts("unsolvable");
    else cout << bfs(start) << endl;

    return 0;
}

 

178. 第K短路

![在这里插入图片描述]( https://img-blog.csdnimg.cn/4bee2df1b88f45ca813eb3ab489e525d.png?x-oss-process=image/watermark ,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAUGFuc2XCtw==,size_20,color_FFFFFF,t_70,g_se,x_16)
样例输入:

2 2
1 2 5
2 1 4
1 2 2

样例输出:

14

代码模板:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<int, PII> PIII;

const int N = 1010, M = 200010;

int n, m, S, T, K;
int h[N], rh[N], e[M], w[M], ne[M], idx;
int dist[N], cnt[N];
bool st[N];

void add(int h[], int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

void dijkstra()
{
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, T});

    memset(dist, 0x3f, sizeof dist);
    dist[T] = 0;

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.y;
        if (st[ver]) continue;
        st[ver] = true;

        for (int i = rh[ver]; ~i; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

int astar()
{
    //当前实际位置 + 估计距离 // 当前实即距离 // 元素 
    //小根堆
    priority_queue<PIII, vector<PIII>, greater<PIII>> heap;
    heap.push({dist[S], {0, S}});

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.y.y, distance = t.y.x;
        cnt[ver] ++ ;
        if (cnt[T] == K) return distance;

        for (int i = h[ver]; ~i; i = ne[i])
        {
            int j = e[i];
            if (cnt[j] < K) //把所有能扩展到的点都加进队列,来求第k最短路
                heap.push({distance + w[i] + dist[j], {distance + w[i], j}});
        }
    }

    return -1;
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    memset(rh, -1, sizeof rh);

    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        //tip: 有向图分别存储正向和反向
        add(h, a, b, c);
        add(rh, b, a, c);
    }
    scanf("%d%d%d", &S, &T, &K);
    if (S == T) K ++ ;
    //预处理估价函数: 当前位置到终点的距离
    dijkstra();
    //A*
    printf("%d\n", astar());

    return 0;
}

 

posted @ 2022-03-22 14:46  panse·  阅读(13)  评论(0)    收藏  举报