zoukankan      html  css  js  c++  java
  • [网络流24题] 孤岛营救问题 (状压搜索 )

    题目链接

    好吧,说是网络流24题,但是我首先想到的是状压搜索

    第一次写状压搜索,竟然一次过,挺惊讶的。

    对于钥匙, 因为只有 10 把, 所以, 我们可以把一个时刻有多少把钥匙,用一个数来表示,比如 0 就表示此时身上一把钥匙都没有, 5 的二进制是 101 从低位开始, 表示他有钥匙 1 和 3
    这样就可以开心的搜索了

    //代码中 从低位开始, 第2表示 钥匙1    第3表示 钥匙2
    #include <bits/stdc++.h>
    const int maxn = 12;
    using namespace std;
    typedef long long ll;
    int xiang[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    struct note
    {
        int x, y, z;        //x y 坐标   z 拥有的钥匙状态
        int bu;         //步数
        note() {}
        note(int x1, int y1, int z1, int bu1)
        {
            x = x1, y = y1, z = z1, bu = bu1;
        }
    } temp;
    int suo[maxn][maxn][maxn][maxn]; //suo[i][j][k][l]  (i,j) --> (k, l) 有某类型的锁
    int yao[maxn][maxn][maxn];       //yao[i][j][k]   (i,j) 有 yao[i][j][0]把钥匙 一个单元格有可能有多把钥匙
    bool vis[maxn][maxn][(1 << 11)]; //标记  vis[i][j][x]  x 是 (i,j)的钥匙状态
    int n, m, p, k;
    
    void bfs()
    {
        temp.x = temp.y = 1;
        temp.bu = temp.z = 0;
        for (int i = 1; i <= yao[1][1][0]; i++) //  初始位置(1,1)可能有钥匙
            temp.z = temp.z | (1 << yao[1][1][i]);
        // printf("%d
    ", temp.z);
        vis[1][1][temp.z] = true;
        queue<note> q;
        q.push(temp);
        int ans = -1;
        while (!q.empty())
        {
            temp = q.front();
            q.pop();
            if (temp.x == n && temp.y == m)
            {
                ans = temp.bu;
                break;
            }
            for (int i = 0; i < 4; i++)
            {
                int tx = temp.x + xiang[i][0];
                int ty = temp.y + xiang[i][1];
                if (tx < 1 || ty < 1 || tx > n || ty > m || suo[temp.x][temp.y][tx][ty] == -1) //越界     本来就过不去
                    continue;
                if (suo[temp.x][temp.y][tx][ty] != 0 && !(temp.z & (1 << suo[temp.x][temp.y][tx][ty]))) //有锁 没钥匙
                    continue;
                if (vis[tx][ty][temp.z] == true)    //这个坐标,同样的钥匙状态已经去过了
                    continue;
                vis[tx][ty][temp.z] = true;     //标记去过
                int tz = temp.z;
                for (int i = 1; i <= yao[tx][ty][0]; i++)
                {
                    tz = tz | (1 << yao[tx][ty][i]);
                }
                vis[tx][ty][tz] = true;         //标记去过   将前后钥匙状态都标记,能减少搜索量
                q.push(note(tx, ty, tz, temp.bu + 1));
            }
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        scanf("%d%d%d", &n, &m, &p);
        scanf("%d", &k);
        while (k--)
        {
            int x1, y1, x2, y2, g;
            scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &g);
            if (g == 0)
                g = -1;
            suo[x1][y1][x2][y2] = g;    // (x1, y1)  ---> (x2, y2) 的路上有一个 g 类型的锁  g = -1 表示不通
            suo[x2][y2][x1][y1] = g;
        }
        scanf("%d", &k);
        while (k--)
        {
            int x, y, q;
            scanf("%d%d%d", &x, &y, &q);
            yao[x][y][0]++;
            yao[x][y][yao[x][y][0]] = q;
        }
        bfs();
        return 0;
    }
    
  • 相关阅读:
    EventBus
    Date 时间 日期 常用方法函数
    线程 Thread Handler
    MySQL-DoubleWrite
    MySQL各版本优化器变化
    MySQL优化器-条件过滤(condition_fanout_filter)
    PXC集群搭建
    mysql主从不一致--relay_log_recovery设置成0
    MySQL5.7-sql_mode
    根据ibd文件进行数据恢复或导入
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337345.html
Copyright © 2011-2022 走看看