• NEU_Train_Camp_2020_搜索和简单图论



    title: NEU_Train_Camp_2020_搜索和简单图论
    date: 2020-07-05 22:38:11
    tags:

    • c++
      categories:
    • New
      cover:

    搜索和简单图论

    A - Knight Moves

    HDU 1372

    每组数据输入两个坐标,(a-h)代表列,(1-8)代表行,得出Knight Move的最小步数
    国际象棋中Knight和中国象棋中马的走法一致,有八个落点.

    标准的,最简单的BFS

    #include <bits/stdc++.h>
    
    using namespace std;
    int dir[8][2] = {{1, -2}, {2, -1}, {2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}}; 
    bool vis[10][10] = {false}; // 记录点是曾经被加入队列
    #define mp(a, b) make_pair(a, b)
    
    int bfs(int sx, int sy, int tx, int ty)
    {
        memset(vis, 0, sizeof(vis));
        queue<pair<int, pair<int, int>>> que; //步数,<x,y>
        vis[sx][sy] = true;
        que.push(mp(0, mp(sx, sy)));
        while (!que.empty())
        {
            pair<int, pair<int, int>> now = que.front();
            que.pop();
            if (now.second.first == tx and now.second.second == ty)
            {
                return now.first;
            }
            for (int i = 0; i < 8; i++)
            {
                int x = now.second.first + dir[i][0];
                int y = now.second.second + dir[i][1];
                if (x >= 1 and x <= 8 and y >= 1 and y <= 8)
                {
                    if (!vis[x][y])
                    {
                        vis[x][y] = true;
                        que.push(mp(now.first + 1, mp(x, y)));
                    }
                }
            }
        }
        return -1;
    }
    int main(void)
    {
        char a, b, c, d;
        while (cin >> a >> b >> c >> d)
        {
            printf("To get from %c%c to %c%c takes %d knight moves.
    ", a, b, c, d, bfs(a - 'a' + 1, b - '0', c - 'a' + 1, d - '0'));
        }
        return 0;
    }
    

    B - Sorting It All Out

    POJ 1094

    每行两个正整数,n,m. 2 <= n <= 26 ,要排序的是前n个大写字母,接下来m行,用<表示两个字母的排序关系.

    输出

    Sorted sequence determined after xxx relations: yyy...y. //在给定x个关系后,得出符合要求的排列
    Sorted sequence cannot be determined.  //排序不唯一
    Inconsistency found after xxx relations.  //条件矛盾,既有向图成环
    

    字母有序排列,形成有向图,进行拓扑排序,判断是否有环,得出解.

    同 [软件依赖] (something)

    #include <vector>
    #include <iostream>
    #include <string>
    #include <queue>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    vector<int> edge[30];
    int indegree[30] = {0};
    int n, m;
    string ans;
    //0 成环 , 1 唯一解 ,2 不确定
    int topoSort()
    {
    
        int temp[30];
        copy(indegree, indegree + 30, temp);
        ans.clear();
        queue<int> que;
        int flag = 1;
        for (int i = 0; i < n; i++)
        {
            if (!indegree[i])
            {
                que.push(i);
            }
        }
        ans.clear();
        while (!que.empty())
        {
            if (que.size() > 1)
                flag = 2;
            int now = que.front();
            que.pop();
            ans.push_back(now + 'A');
            for (int i = 0; i < edge[now].size(); i++)
            {
                if (--temp[edge[now][i]] == 0)
                {
                    que.push(edge[now][i]);
                }
            }
        }
        if (ans.size() != n)
            flag = 0;
        return flag;
    }
    inline int num(char a)
    {
        return a - 'A';
    }
    int main(void)
    {
        while (cin >> n >> m and (n or m))
        {
            memset(indegree, 0, sizeof(indegree));
            for (int i = 0; i < 30; i++)
            {
                edge[i].clear();
            }
            bool done = false;
            int res;
            for (int i = 0; i < m; i++)
            {
                char a, b, c;
                cin >> a >> b >> c;
                if (done)
                    continue;
                edge[num(a)].push_back(num(c));
                indegree[num(c)]++;
                res = topoSort();
                if (res == 0)
                {
                    done = true;
                    cout << "Inconsistency found after " << i + 1 << " relations." << endl;
                }
                else if (res == 1)
                {
                    done = true;
                    cout << "Sorted sequence determined after " << i + 1 << " relations: ";
                    // for (auto &&j : ans)
                    cout << ans;
                    cout << ".
    ";
                }
            }
            if (res == 2)
            {
                cout << "Sorted sequence cannot be determined." << endl;
            }
        }
        return 0;
    }
    

    C - Eight

    HDU 1043

    题意描述:给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数,输出走法。

    难点在于将这个矩阵hash,使用unordered_set会MLE,这里使用的是康托展开.

    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    #include <stdlib.h>
    #include <cctype>
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #define mem(a, x) memset(a, x, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int dx[] = {-1, 1, 0, 0};
    const int dy[] = {0, 0, -1, 1}; //上下左右
    const char dd[] = "durl";
    const int ans = 46234; //123456780
    int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
    int ct(int s[])
    {
        int sun = 0, tmp;
        for (int i = 0; i < 9; i++)
        {
            tmp = 0;
            for (int j = i + 1; j < 9; j++)
                if (s[j] < s[i])
                    tmp++;
            sun += (tmp * fac[9 - i - 1]);
        }
        return sun + 1;
    }
    struct Node
    {
        int g[10];
        int x;
        int st;
    } h;
    struct No
    {
        int fa;
        char mo;
    } moo[400000];
    bool vis[400000];
    void bfs()
    {
        queue<Node> q;
        q.push(h);
        vis[h.st] = 1;
        while (!q.empty())
        {
            h = q.front();
            q.pop();
            int x = h.x / 3;
            int y = h.x % 3;
            for (int i = 0; i < 4; ++i)
            {
                int xx = x + dx[i];
                int yy = y + dy[i];
                if (xx >= 0 && yy >= 0 && xx < 3 && yy < 3)
                {
                    Node nx = h;
                    nx.x = xx * 3 + yy;
                    swap(nx.g[h.x], nx.g[nx.x]);
                    nx.st = ct(nx.g);
                    if (!vis[nx.st])
                    {
                        vis[nx.st] = 1;
                        moo[nx.st].mo = dd[i];
                        moo[nx.st].fa = h.st;
                        q.push(nx);
                    }
                }
            }
        }
    }
    void init()
    {
        for (int i = 0; i < 8; ++i)
            h.g[i] = i + 1;
        h.g[8] = 0;
        h.x = 8;
        h.st = ans;
        moo[ans].fa = -1;
        bfs();
    }
    int main()
    {
        char tmp;
        init();
        int s[10];
        while (cin >> tmp)
        {
            if (tmp == 'x')
                s[0] = 0;
            else
                s[0] = tmp - 48;
            for (int i = 1; i < 9; ++i)
            {
                cin >> tmp;
                if (tmp == 'x')
                    s[i] = 0;
                else
                    s[i] = tmp - 48;
            }
            int st = ct(s);
            if (st == ans)
            {
                puts("");
                continue;
            }
            if (!vis[st])
                printf("unsolvable
    ");
            else
            {
                while (moo[st].fa != -1)
                {
                    printf("%c", moo[st].mo);
                    st = moo[st].fa;
                }
                puts("");
            }
        }
        return 0;
    }
    

    UNSOLVED_D - Vin Diagrams

    ICPC 7982 - Vin Diagrams

    E - 最短路径·三:SPFA算法

    HihoCoder - 1093

    SPFA

    SPFA是运用队列,把所有的点遍历到没有能更新的,点可以重复入队

    关于SPFA,它死了

    仅用于判断负权环,没有负权边的最短路使用dijkstra

    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    
    using namespace std;
    const int N = 100005;
    int n, m, s, t, dist[N]; //到起点的最短距离
    bool in[N];
    vector<pair<int, int>> v[N]; //编号,距离
    
    int SPFA()
    {
        queue<int> Q;
        for (int i = 1; i <= n; i++)
            dist[i] = __INT32_MAX__, in[i] = false;
        dist[s] = 0;
        Q.push(s);
        in[s] = true;
        while (!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            in[u] = false;
            for (int i = v[u].size() - 1; i >= 0; i--)
            {
                int j = v[u][i].first;
                if (dist[j] > dist[u] + v[u][i].second)
                {
                    dist[j] = dist[u] + v[u][i].second;
                    if (!in[j])
                    {
                        Q.push(j);
                        in[j] = true;
                    }
                }
            }
        }
        return dist[t];
    }
    int main()
    {
        cin >> n >> m >> s >> t;
        int x, y, c;
        for (int i = 1; i <= m; i++)
        {
            cin >> x >> y >> c;
            v[x].push_back(make_pair(y, c));
            v[y].push_back(make_pair(x, c));
        }
        cout << SPFA();
    }
    

    dijkstra

    dijkstra是每次找出离源点最近的点确定位置,不可重复确定

    Dijkstra使用优先队列,虽然同一个点可以多次入队,但是保证了一个点真正pop出来刷新其他点的时候只有一次.

    https://blog.csdn.net/Newbie006/article/details/79674791

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 1e5 + 10;
    int n, m, s, t;
    using p = pair<int, int>;
    vector<p> edge[MAXN]; // 距离 , 序号
    int dis[MAXN];
    
    int dijkstra()
    {
        priority_queue<p, vector<p>, greater<p>> que; // 距离,序号;
        fill(dis, dis + 1 + n, __INT32_MAX__);
        dis[s] = 0;
        que.push(make_pair(0, s));
        while (!que.empty())
        {
            int d = que.top().first, num = que.top().second;
            que.pop();
            if (dis[num] < d) 
                continue;
            for (int i = 0; i < edge[num].size(); i++)
            {
                p temp = edge[num][i];
                if (dis[temp.second] > dis[num] + temp.first)
                {
                    dis[temp.second] = dis[num] + temp.first;
                    que.push(make_pair(dis[temp.second], temp.second));
                }
            }
        }
        return dis[t];
    }
    
    int main(void)
    {
        cin >> n >> m >> s >> t;
        for (int i = 0; i < m; i++)
        {
            int a, b, c;
            cin >> a >> b >> c;
            edge[a].push_back(make_pair(c, b));
            edge[b].push_back(make_pair(c, a));
        }
        cout << dijkstra();
        return 0;
    }
    

    F - Flight

    HDU - 3499

    题意:有一个n个结点,m条边的有向图,可以对一条边进行边权减半的操作。问起点到终点的最短路

    分层图最短路dijkstra

    仅对字符串进行hash,不需要按序输出,unordered_map更优

    asd

    dis[]数组不用ll,会wa

    #include <iostream>
    #include <unordered_map>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <map>
    #define mp(a, b) make_pair(a, b)
    using namespace std;
    using ll = long long;
    ll dis[200002]; //保存距离的数组要用ll,否则会wa
    // map<string, int> mapp;  使用unordered_map , 耗时缩短一半
    unordered_map<string, int> mapp;
    using p = pair<int, int>; //这里不能用ll,否则会mle
    vector<p> edge[200002];
    
    
    void dijkstra(int start) //分层最短路的dijkstra()就是模板,没有变化
    {
        priority_queue<p, vector<p>, greater<p>> que;
        que.push(mp(0, start));
        dis[start] = 0;
        while (!que.empty())
        {
            p now = que.top();
            que.pop();
            if (now.first > dis[now.second])
                continue;
            for (int i = 0; i < edge[now.second].size(); i++)
            {
                p next = edge[now.second][i];
                if (dis[next.second] > dis[now.second] + next.first)
                {
                    dis[next.second] = dis[now.second] + next.first;
                    que.push(mp(dis[next.second], next.second));
                }
            }
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int n, m;
        while (cin >> n >> m)
        {
            int id = 1;
            mapp.clear();
            for (int i = 0; i < 2 * n + 2; i++)
            {
                edge[i].clear();
                dis[i] = __LONG_LONG_MAX__;
            }
            for (int i = 0; i < m; i++)
            {
                string a, b;
                int val;
                cin >> a >> b >> val;
                if (!mapp[a])
                    mapp[a] = id++;
                if (!mapp[b])
                    mapp[b] = id++;
                edge[mapp[a]].push_back(mp(val, mapp[b])); //第一层
                edge[mapp[a] + n].push_back(mp(val, mapp[b] + n)); //第二层
                edge[mapp[a]].push_back(mp(val / 2, mapp[b] + n)); //第一层到第二层,就是使用打折机票
            }
            string start, end;
            cin >> start >> end;
            if (m == 0)
            {
                cout << -1 << endl;
                continue;
            }
            dijkstra(mapp[start]);
            ll ans = min(dis[mapp[end]], dis[mapp[end] + n]);
            if (ans == __LONG_LONG_MAX__)
                ans = -1;
            cout << ans << endl;
        }
    }
    

    G - Free DIY Tour

    HDU-1224

    最长路

    基于dijkstra的最长路

    #include <iostream>
    #include <stack>
    #include <queue>
    
    #define mp(a, b) make_pair(a, b)
    using namespace std;
    using p = pair<int, int>;
    vector<pair<int, int>> edge[110];
    int dis[110];
    int path[110];
    void dijkstra(int tar)
    {
        priority_queue<pair<int, int>> que;
        que.push(mp(0, 1));
        dis[1] = 0;
        while (!que.empty())
        {
            p now = que.top();
            que.pop();
            if (now.first < dis[now.second])
                continue;
            for (int i = 0; i < edge[now.second].size(); i++)
            {
                p t = edge[now.second][i];
                if (dis[t.second] < dis[now.second] + t.first)
                {
                    dis[t.second] = dis[now.second] + t.first;
                    que.push(mp(dis[t.second], t.second));
                    path[t.second] = now.second;
                }
            }
        }
        cout << "points : " << dis[tar] << endl;
        cout << "circuit : ";
        stack<int> q;
        q.push(1);
        tar = path[tar];
        while (tar != -1)
        {
            q.push(tar);
            tar = path[tar];
        }
        q.pop();
        cout << 1;
        while (!q.empty())
        {
            cout << "->" << q.top();
            q.pop();
        }
        cout << endl;
    }
    
    int main(void)
    {
        int t;
        cin >> t;
        for (int j = 0; j < t; j++)
        {
            int n;
            cin >> n;
            vector<int> val;
            val.resize(n + 1);
            fill(path, path + 110, -1);
            fill(dis, dis + 110, -1);
            for (int i = 0; i < n; i++)
            {
                edge[i].clear();
                cin >> val[i];
            }
            val[n] = 0;
            int k;
            cin >> k;
            for (int i = 0; i < k; i++)
            {
                int a, b;
                cin >> a >> b;
                edge[a].push_back(mp(val[b - 1], b));
            }
            if (j != 0)
                cout << endl;
            cout << "CASE " << j + 1 << "#" << endl;
            dijkstra(n + 1);
        }
        return 0;
    }
    
    

    基于SPFA的最长路

    #include <iostream>
    #include <cstdio>
    #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    #include <math.h>
    #include <memory>
    #include <queue>
    using namespace std;
    typedef long long LL;
    #define max_v 120
    int n, m;
    int G[max_v][max_v];
    int a[max_v];
    int dis[max_v]; //保存價值
    int way[max_v]; //保存路
    void spfa(int s, int tn)
    {
        for (int i = 1; i <= tn; i++)
        {
            dis[i] = 0;
            way[i] = 0;
        }
        queue<int> q;
        q.push(s);
    
        int p;
        while (!q.empty())
        {
            p = q.front();
            q.pop();
    
            for (int i = 1; i <= tn; i++)
            {
                if (G[p][i] != 0)
                {
                    if (dis[p] + a[i] > dis[i])
                    {
                        dis[i] = dis[p] + a[i];
                        way[i] = p;
                        q.push(i);
                    }
                }
            }
        }
    }
    void pri(int tn) //路徑打印
    {
        int a[300];
        int c = 1;
        int i = tn;
        while (way[i])
        {
            a[c++] = way[i];
            i = way[i];
        }
        for (int i = c - 1; i >= 1; i--)
        {
            printf("%d->", a[i]);
        }
        printf("1
    ");
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        int k = 1;
        while (t--)
        {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
            {
                scanf("%d", &a[i]);
            }
            a[n + 1] = 0;
            scanf("%d", &m);
            memset(G, 0, sizeof(G));
            for (int i = 1; i <= m; i++)
            {
                int x, y;
                scanf("%d %d", &x, &y);
                G[x][y] = 1;
            }
            spfa(1, n + 1);
            if (k != 1)
                printf("
    ");
            printf("CASE %d#
    ", k++);
            printf("points : %d
    ", dis[n + 1]);
            printf("circuit : ");
            pri(n + 1);
        }
        return 0;
    }
    

    H - 棋盘问题

    POJ - 1321

    #include <iostream>
    
    using namespace std;
    int n, k;
    bool board[10][10];
    bool vis[10];
    int ans, cnt;
    
    void dfs(int cur)
    {
        if (cnt == k)
        {
            ans++;
            return;
        }
        if (cur > n - 1) // 0 - n-1
        {
            return;
        }
        for (int i = 0; i < n; i++)
        {
            if (vis[i] == false and board[cur][i])
            {
                vis[i] = true;
                cnt++;
                dfs(cur + 1);
                vis[i] = false;
                cnt--;
            }
        }
        dfs(cur + 1);
    }
    
    int main()
    {
        while (cin >> n >> k and n != -1 and k != -1)
        {
            cnt = ans = 0;
            fill(vis, vis + 10, false);
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    char t;
                    cin >> t;
                    board[i][j] = (t == '#' ? true : false);
                }
            }
            dfs(0);
            cout << ans << endl;
        }
    }
    

    I - Dungeon Master

    POJ - 2251

    三维迷宫问题,简单的BFS,搜索六个方向.

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    using namespace std;
    
    struct node
    {
        int x, y, z, m;
        node(int x, int y, int z, int m) : x(x), y(y), z(z), m(m) {}
    };
    
    int l, r, c;
    char board[35][35][35];
    bool vis[35][35][35];
    int sx, sy, sz, ex, ey, ez;
    //向北、向南、向东、向西移动,向上或向下移动一个单位
    int dir[6][3] = {{1, 0, 0},
                     {-1, 0, 0},
                     {0, 1, 0},
                     {0, -1, 0},
                     {0, 0, 1},
                     {0, 0, -1}};
    
    int bfs()
    {
        queue<node> que;
        que.push(node(sx, sy, sz, 0));
        vis[sx][sy][sz] = true;
        while (!que.empty())
        {
            node top = que.front();
            que.pop();
            if (top.x == ex and top.y == ey and top.z == ez)
            {
                return top.m;
            }
            for (int i = 0; i < 6; i++)
            {
                int x = dir[i][0] + top.x;
                int y = dir[i][1] + top.y;
                int z = dir[i][2] + top.z;
                if (vis[x][y][z] == false and x >= 0 and x < l and y >= 0 and y < r and z >= 0 and z < c and board[x][y][z] != '#')
                {
                    vis[x][y][z] = true;
                    que.push(node(x, y, z, top.m + 1));
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        while (cin >> l >> r >> c and l != 0 and r != 0 and c != 0)
        {
            // memset(vis, sizeof(vis), 0);  //脑瘫错误,找了好久
            memset(vis, 0, sizeof(vis));
            for (int i = 0; i < l; i++)
            {
                for (int j = 0; j < r; j++)
                {
                    for (int k = 0; k < c; k++)
                    {
                        cin >> board[i][j][k];
                        if (board[i][j][k] == 'S')
                        {
                            sx = i, sy = j, sz = k;
                        }
                        if (board[i][j][k] == 'E')
                        {
                            ex = i, ey = j, ez = k;
                        }
                    }
                }
            }
            int ans = bfs();
            if (ans == -1)
                cout << "Trapped!" << endl;
            else
                cout << "Escaped in " << ans << " minute(s)." << endl;
        }
    
        return 0;
    }
    

    我吐了,memset用错了,找了好久.
    学习下std::fill()的用法,使用它

    关于memset()的限制

    因为memset赋值时按照字节填充,所以更适合给char类型的数组赋值(一维/二维),因为在c/c++中char占用1一个字节(8位),而int占用2个字节,如果要使用memset给int赋值只适用于0,-1,但还有一种巧妙的方法,如果要将一个数组(一维/二维)全部赋值一个很大的值也可以通过将这个最大值M设置为0x3f3f3f3f(这是一个很巧妙的数字具体有兴趣的童鞋可以去查一下原因哦)

    memset也可对浮点数组赋 0 值 ( 使用IEEE-754标准 ), 一些讨论见 Stackoverflow

    关于std::fill()

    定义于头文件 , 复杂度:准确赋值 last - first 次。

        int b[10];
        fill(b, b + 10, -1);
    
        int c[10][10];
        fill(c[0], c[0] + 10 * 10, -1);
    
        int a[20][20][20];
        fill(a[0][0], a[0][0] + 20 * 20 * 20, -1);
    

    o2以上的优化时,std::fill()memset的性能表现相近,简单测试可见StackOverflow

    J - Flip Game UNSOLVED_

    POJ - 1753

    K - 非常可乐

    HDU - 1495

    bfs

    #include <iostream>
    #include <queue>
    #include <cstring>
    using namespace std;
    int s, n, m; //S==N+M
    bool vis[101][101][101];
    int bottle[3];
    struct node
    {
        int cap[3], step;
        node(int a, int b, int c, int d)
        {
            cap[0] = a;
            cap[1] = b;
            cap[2] = c;
            step = d;
        }
    };
    
    bool judge(node &t)
    {
        if ((t.cap[0] == 0 and t.cap[1] == t.cap[2]) or (t.cap[1] == 0 and t.cap[0] == t.cap[2]) or (t.cap[2] == 0 and t.cap[0] == t.cap[1]))
            return true;
        return false;
    }
    
    int bfs()
    {
        memset(vis, 0, sizeof(vis));
        queue<node> que;
        que.push(node(s, 0, 0, 0));
        vis[s][0][0] = true;
        while (!que.empty())
        {
            node top = que.front();
            que.pop();
            if (judge(top))
                return top.step;
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (i != j)
                    {
                        if (top.cap[i] == 0)
                            continue;
                        else
                        {
                            node t = top;
                            if (t.cap[i] + t.cap[j] < bottle[j])
                            {
                                t.cap[j] += t.cap[i];
                                t.cap[i] = 0;
                            }
                            else
                            {
                                t.cap[i] -= (bottle[j] - t.cap[j]);
                                t.cap[j] = bottle[j];
                            }
                            if (vis[t.cap[0]][t.cap[1]][t.cap[2]] == false)
                            {
                                vis[t.cap[0]][t.cap[1]][t.cap[2]] = true;
                                que.push(node(t.cap[0], t.cap[1], t.cap[2], t.step + 1));
                            }
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    int main()
    {
    
        while (cin >> s >> n >> m and s != 0 and n != 0 and m != 0)
        {
            if (s % 2 == 1)
            {
                cout << "NO" << endl;
                continue;
            }
            bottle[0] = s;
            bottle[1] = n;
            bottle[2] = m;
            int ans = bfs();
            if (ans == -1)
                cout << "NO" << endl;
            else
                cout << ans << endl;
        }
        return 0;
    }
    

    L - Prime Path UNSOLVED_

    POJ - 3126

    M - Find a way

    HDU - 2612

    两次简单的bfs

    因为continuewa 好几次

    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <vector>
    using namespace std;
    
    char board[202][202];
    bool vis[202][202];
    int n, m;
    int start[2][2];
    struct node
    {
        int x, y, step;
        node(int x, int y, int s) : x(x), y(y), step(s) {}
    };
    vector<node> ans[2];
    int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
    void bfs(int x, int y, int who)
    {
        memset(vis, 0, sizeof(vis));
        queue<node> que;
        que.push(node(x, y, 0));
        vis[x][y] = true;
        while (!que.empty())
        {
            node now = que.front();
            que.pop();
            if (board[now.x][now.y] == '@')
            {
                ans[who].push_back(node(now.x, now.y, now.step));
                // continue;  这里wa好几次
            }
            for (int i = 0; i < 4; i++)
            {
                int tx = now.x + dir[i][0];
                int ty = now.y + dir[i][1];
                if (tx >= 0 and tx < n and ty >= 0 and ty < m and board[tx][ty] != '#' and !vis[tx][ty])
                {
                    vis[tx][ty] = true;
                    que.push(node(tx, ty, now.step + 1));
                }
            }
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        while (cin >> n >> m)
        {
            ans[0].clear();
            ans[1].clear();
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    cin >> board[i][j];
                    if (board[i][j] == 'Y')
                    {
                        start[0][0] = i;
                        start[0][1] = j;
                    }
                    if (board[i][j] == 'M')
                    {
                        start[1][0] = i;
                        start[1][1] = j;
                    }
                }
            }
            bfs(start[0][0], start[0][1], 0);
            bfs(start[1][0], start[1][1], 1);
            int res = __INT32_MAX__;
            for (int i = 0; i < ans[0].size(); i++)
            {
                for (int j = 0; j < ans[1].size(); j++)
                {
                    if (ans[0][i].x == ans[1][j].x and ans[0][i].y == ans[1][j].y)
                    {
                        res = min(res, ans[0][i].step + ans[1][j].step);
                    }
                }
            }
            cout << res * 11 << endl;
        }
        return 0;
    }
    

    N - Shuffle'm Up

    POJ - 3087

    直接模拟

    #include <iostream>
    #include <string>
    // #include <unordered_set>  POJ 貌似不支持C++11及以上标准
    #include <set>
    using namespace std;
    
    int main()
    {
        int t;
        cin >> t;
        for (int i = 0; i < t; i++)
        {
            string tar;
            int c;
            set<string> vis;
            vis.clear();
            cin >> c;
            string a, b;
            cin >> a >> b;
            cin >> tar;
            string t;
            int count(0);
            cout << i + 1 << ' ';
            while (true)
            {
                t.clear();
                for (int i = 0; i < c; i++)
                {
                    t.push_back(b[i]);
                    t.push_back(a[i]);
                }
                count++;
                if (vis.find(t) == vis.end())
                {
                    vis.insert(t);
                }
                else
                {
                    cout << -1 << endl;
                    break;
                }
                if (t == tar)
                {
                    cout << count << endl;
                    break;
                }
                a.clear();
                b.clear();
                for (int i = 0; i < c; i++)
                {
                    a.push_back(t[i]);
                }
                for (int i = c; i < 2 * c; i++)
                {
                    b.push_back(t[i]);
                }
            }
        }
        return 0;
    }
    

    O - Pots

    POJ - 3414

    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    int a, b, c;
    
    // FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap;
    // DROP(i)      empty the pot i to the drain;
    // POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
    string path[] = {
        "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
    struct node
    {
        int a, b;
        vector<int> id;
    };
    bool vis[101][101] = {false};
    
    void bfs()
    {
        queue<node> que;
        node t;
        t.a = 0;
        t.b = 0;
        que.push(t);
        vis[a][b] = true;
        while (!que.empty())
        {
            node now = que.front();
            que.pop();
            if (now.a == c or now.b == c)
            {
                cout << now.id.size() << endl;
                for (int i = 0; i < now.id.size(); i++)
                {
                    cout << path[now.id[i]] << endl;
                }
                return;
            }
            t = now;
            if (t.a != a)
            {
                t.a = a;
                t.b = now.b;
                t.id = now.id;
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(0);
                    que.push(t);
                }
            }
            t = now;
            if (t.b != b)
            {
                t.a = now.a;
                t.b = b;
                t.id = now.id;
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(1);
                    que.push(t);
                }
            }
            // "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
            // DROP(a)
            t = now;
            if (t.a)
            {
                t.a = 0;
                t.b = now.b;
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(2);
                    que.push(t);
                }
            }
            // DROP(b)
            t = now;
            if (t.b)
            {
                t.b = 0;
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(3);
                    que.push(t);
                }
            }
            // POUR(a,b)
            t = now;
            if (t.a && (t.b < b))
            {
                if (t.a > (b - t.b))
                {
                    t.a = now.a - (b - now.b);
                    t.b = b;
                }
                else
                {
                    t.a = 0;
                    t.b = now.b + now.a;
                }
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(4);
                    que.push(t);
                }
            }
            // POUR(b,a)
            t = now;
            if (t.b && (t.a < a))
            {
                if (t.b > (a - t.a))
                {
                    t.a = a;
                    t.b = now.b - (a - now.a);
                }
                else
                {
                    t.a = now.a + now.b;
                    t.b = 0;
                }
                if (!vis[t.a][t.b])
                {
                    vis[t.a][t.b] = true;
                    t.id.push_back(5);
                    que.push(t);
                }
            }
        }
        cout << "impossible" << endl;
    }
    
    int main()
    {
        cin >> a >> b >> c;
        bfs();
        return 0;
    }
    

    P - Fire!

    UVA - 11624

    https://blog.csdn.net/PK__PK/article/details/79116110

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <iostream> 
    #include <queue>
    using namespace std;
    const int maxn = 1010;
    char map[maxn][maxn]; // 地圖
    int book[maxn][maxn]; // 標記陣列,記錄這點火或者人是否走過
    
    struct node
    {
        int x;    //座標x
        int y;    // 座標y
        int step; // 人的步數
        int kind; // 用來區分是人還是火,1是人,0是火
    };
    
    queue<node> q;
    int n, m, ans;                              // n,m表示長寬。ans表示火的個數
    node ren;                                   //記錄人的起始位置
    node fire[maxn];                            // 記錄火的起始位置
    int mov[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; // 移動陣列
    void bfs()
    {
        node now, next;
        for (int i = 0; i < ans; i++)
        { // 先把火入佇列
            q.push(fire[i]);
        }
        q.push(ren); // 再把人放入佇列
                     //	cout<<ren.step<<endl;
        while (!q.empty())
        {
            now = q.front();
            q.pop();
            if (now.kind == 1 && (now.x == 0 || now.y == 0 || now.x == n - 1 || now.y == m - 1))
            { // 當是人到達邊緣時
                cout << now.step + 1 << endl;
                return;
            }
            for (int i = 0; i < 4; i++)
            { // 對火對人進行移動
                next.x = now.x + mov[i][0];
                next.y = now.y + mov[i][1];
                if (next.x < 0 || next.x >= n || next.y < 0 || next.y >= m || book[next.x][next.y] == 1 || map[next.x][next.y] == '#') //判斷是否可走和越界
                    continue;
                next.kind = now.kind;     // 記錄種類
                book[next.x][next.y] = 1; // 標記已走
                                          //	printf("%d %d %d
    ",next.x,next.y,next.step);
                if (now.kind)             // 若為人 順帶記錄步數
                    next.step = now.step + 1;
                q.push(next); //入佇列
            }
        }
        cout << "IMPOSSIBLE" << endl;
    }
    int main()
    {
        int z;
        cin >> z;
        while (z--)
        {
            while (!q.empty())
                q.pop(); // 清空很重要
            memset(map, 0, sizeof(map));
            memset(book, 0, sizeof(book));
            ans = 0;
            cin >> n >> m;
            for (int i = 0; i < n; i++)
                cin >> map[i]; // 輸入地圖資訊
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    if (map[i][j] == 'J')
                    { // 查詢人的起始位置
                        ren.x = i;
                        ren.y = j;
                        ren.step = 0;
                        ren.kind = 1;
                    }
                    if (map[i][j] == 'F')
                    { // 查詢所有火的起始位置
                        fire[ans].x = i;
                        fire[ans].y = j;
                        fire[ans].kind = 0;
                        fire[ans].step = 0;
                        ans++;
                        book[i][j] = 1;
                    }
                }
            }
            bfs();
        }
        return 0;
    }
    /*
    4 4
    ####
    #JF#
    #..#
    #..#
    3 3
    ###
    #J.
    #.F
    */
    
  • 相关阅读:
    杭电2007
    杭电 2004
    杭电2005
    杭电2001
    杭电 2000
    Section One
    杭电oj 1002
    杭电oj 1001
    JavaScript高级程序设计第14章表单脚本 (学习笔记)
    JavaScript高级程序设计(学习笔记)
  • 原文地址:https://www.cnblogs.com/Delta2019/p/13369662.html
Copyright © 2020-2023  润新知