NEU_Train_Camp_2020_搜索和简单图论

搜索和简单图论

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.\n", 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 << ".\n";
            }
        }
        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\n");
        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\n");
}
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("\n");
        printf("CASE %d#\n", k++);
        printf("points : %d\n", 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\n",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
*/
posted @ 2020-07-23 23:50  Delta_in_Cnblogs  阅读(129)  评论(0编辑  收藏  举报