1. 程式人生 > >kuangbin專題 簡單搜尋(bfs+dfs) 個人題解

kuangbin專題 簡單搜尋(bfs+dfs) 個人題解

VJ:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=80667#overview

出處:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65959#overview

越寫到後面越是順手,1次AC的越來越多,並且英文題目也讀的越來越順,算是一種進步吧。

A POJ 1321

窮舉組合數dfs暴力,注意一個點確定那麼那行那列就不能放

//組合數的回溯法
//用cstring或string.h 不要用memory.h
#include<iostream>
#include<cstring>
using namespace std;

const int maxn = 100;
int n, k;
int px[maxn], py[maxn];
int all;
int ans;
int visited[maxn];
int vx[9], vy[9];

void dfs(int num, int cur);

int main()
{
    ios::sync_with_stdio(false);
    while (cin >> n >> k)
    {
        if (n == -1 && k == -1)break;
        ans = 0;
        all = 0;
        memset(px, 0, sizeof(px));
        memset(py, 0, sizeof(py));
        memset(visited, 0, sizeof(visited));
        char chTmp;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                cin >> chTmp;
                if (chTmp == '#')
                {
                    px[all] = i;
                    py[all] = j;
                    all++;
                }
            }
            cin.ignore();
        }
        dfs(0, 0);
        cout << ans << endl;
    }
    return 0;
}

void dfs(int num, int cur)
{
    if (cur == k)
    {
        ans++;
    }
    else
    {
        for (int i = num; i < all; i++)
        {
            if (visited[i] == 0 && vx[px[i]] == 0 && vy[py[i]] == 0)
            {
                visited[i] = 1;
                vx[px[i]]++;
                vy[py[i]]++;
                dfs(i + 1, cur + 1);
                visited[i] = 0;
                vx[px[i]]--;
                vy[py[i]]--;
            }
        }
    }
}


B POJ 2251

3DBFS,擴充套件而已。水題

#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;

int L, R, C;
const int maxn = 32;

struct Node
{
    int l, r, c;
    int path;
    //-1 = #     1 = .   2 = E
    int own;
    void assign(int x, int y, int z)
    {
        l = x; r = y; c = z;
        path = -1;
        own = 0;
    }
}node[maxn][maxn][maxn];
queue<Node> Q;

int bfs()
{
    Node temp;
    while (!Q.empty())
    {
        temp = Q.front();
        if (temp.own == 2)return temp.path;
        for (int dl = -1; dl < 2; dl++)
            for (int dr = -1; dr < 2; dr++)
                for (int dc = -1; dc < 2; dc++)
                {
                    int a[3] = { dl, dr, dc };
                    sort(a, a + 3);
                    if (!((a[0] == 0 && a[1] == 0) || (a[1] == 0 && a[2] == 0)))continue;
                    if (temp.l + dl > 0 && temp.l + dl <= L && temp.r + dr > 0 && temp.r + dr <= R && temp.c + dc > 0 && temp.c + dc <= C && node[temp.l + dl][temp.r + dr][temp.c + dc].own > 0 && node[temp.l + dl][temp.r + dr][temp.c + dc].path < 0)
                    {
                        node[temp.l + dl][temp.r + dr][temp.c + dc].path = node[temp.l][temp.r][temp.c].path + 1;
                        Q.push(node[temp.l + dl][temp.r + dr][temp.c + dc]);
                    }
                }
        Q.pop();
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);
    while (cin >> L >> R >> C)
    {
        if (L == 0 && R == 0 && C == 0)break;
        while (!Q.empty())Q.pop();
        string tmp;
        for (int i = 1; i <= L; i++)
        {
            for (int j = 1; j <= R; j++)
            {
                cin >> tmp;
                for (int k = 1; k <= C; k++)
                {
                    node[i][j][k].assign(i, j, k);
                    switch (tmp[k - 1])
                    {
                    case '.':node[i][j][k].own = 1; break;
                    case 'S':node[i][j][k].own = 1; node[i][j][k].path = 0; Q.push(node[i][j][k]); break;
                    case 'E':node[i][j][k].own = 2; break;
                    }
                }
            }
        }
        int ans = bfs();
        if (ans == 0)cout << "Trapped!\n";
        else cout << "Escaped in " << ans << " minute(s).\n";
    }
    return 0;
}


C POJ 3278

隱式bfs。水題

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

const int maxn = 100001;

int N, K;
queue<int> Q;
int path[maxn];

int main()
{
    cin >> N >> K;
    memset(path, -1, sizeof(path));
    path[N] = 0;
    Q.push(N);
    int temp;
    while (!Q.empty())
    {
        temp = Q.front();
        Q.pop();
        if (temp == K) { cout << path[temp] << endl; }
        if (temp > 0 && path[temp - 1] < 0)
        {
            Q.push(temp - 1);
            path[temp - 1] = path[temp] + 1;
        }
        if (temp < 100000 && path[temp + 1] < 0)
        {
            Q.push(temp + 1);
            path[temp + 1] = path[temp] + 1;
        }
        if (temp * 2 < maxn && path[temp * 2] < 0)
        {
            Q.push(temp * 2);
            path[temp * 2] = path[temp] + 1;
        }
    }
    return 0;
}


D POJ 3279

值得注意的是第一行一旦確定後面行也確定。從這點出發的暴力運算量就可以AC

//顯然每個位置只能為0或1,不可能為2
//而當第一行一旦確定,後面的m-1行也就確定
//因此只要窮舉第一行的情況,1<<16的運算量,再選字典序最小即可
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

int M, N;
int m[17][17];
int map[17][17];
int ans[17][17];
int minans[17][17];
int minp = (1 << 30);
int minv = (1 << 30);
const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };

void flip(int row, int col)
{
    if (map[row][col] == 0)map[row][col] = 1;
    else map[row][col] = 0;
    for (int i = 0; i < 4; i++)
    {
        if (row + dx[i] < 0 || row + dx[i] > M - 1 || col + dy[i] < 0 || col + dy[i] > N - 1)continue;
        if (map[row + dx[i]][col + dy[i]] == 0)map[row + dx[i]][col + dy[i]] = 1;
        else map[row + dx[i]][col + dy[i]] = 0;
    }
}

int main()
{
    cin >> M >> N;
    memset(m, -1, sizeof(m));
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
            cin >> m[i][j];
    }
    bool fuck = false;
    for (int i = 0; i < (1 << N); i++)
    {
        memset(ans, 0, sizeof(ans));
        for (int x = 0; x < M; x++)
        {
            for (int y = 0; y < N; y++)
                map[x][y] = m[x][y];
        }
        for (int j = 0; j < N; j++)
        {
            ans[0][j] = (i & (1 << j));
            if (ans[0][j] > 0)
            {
                ans[0][j] = 1;
                flip(0, j);

            }
        }
        for (int j = 1; j < M; j++)
        {
            for (int k = 0; k < N; k++)
            {
                if (map[j - 1][k] == 1)
                {
                    flip(j, k);
                    ans[j][k] = 1;
                }
            }

        }
        bool zz = true;
        for (int j = 0; j < N; j++)
        {
            if (map[M - 1][j] == 1)
            {
                zz = false;
                break;
            }
        }
        if (zz)
        {
            fuck = true;
            int p = 0;
            for (int k = 0; k < M; k++)
                for (int j = 0; j < N; j++)
                {
                    p += ans[k][j];
                }
            if (p < minv || (p == minv && minp > i))
            {
                minv = p;
                minp = i;
                memcpy(minans, ans, sizeof(ans));
            }
        }
    }
    if (!fuck)cout << "IMPOSSIBLE\n";
    else
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N - 1; j++)
            {
                cout << minans[i][j] << " ";
            }
            cout << minans[i][N - 1] << endl;
        }
    }
    return 0;
}


E POJ 1426

隱式bfs剪枝,從最高位1開始。利用數論的知識來優化就不會爆炸

//第一位必定為1 選最小的即可
//從最高位開始向後bfs,補0或1
//剪枝:對於完全剩餘系0-n-1
//比如在第3位出現了k,而到第9位為0,結束
//那麼我在第6位又出現k,顯然到12位就會為0
//因此可以直接把又出現k的情況直接扔掉
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

int N;

struct Node
{
    int value;
    int pos;
    int store[205];
    Node() {}
    Node(int a) :pos(a), value(1) { memset(store, 0, sizeof(store)); store[a] = 1; }
    Node(Node n, int p)
    {
        pos = n.pos + 1;
        value = (n.value * 10 + p) % N;
        memcpy(store, n.store, sizeof(store));
        store[pos] = p;
    }
    void print()
    {
        for (int i = 1; i <= pos; i++)
        {
            cout << store[i];
        }
        cout << endl;
    }
};

Node first;
queue<Node> Q;
int visited[205];

int main()
{
    while (cin >> N && N > 0)
    {
        memset(visited, 0, sizeof(visited));
        while (!Q.empty())
        {
            Q.pop();
        }
        first = Node(1);
        Q.push(first);
        while (!Q.empty())
        {
            first = Q.front();
            Q.pop();
            if (visited[first.value] == 1)continue;
            else visited[first.value] = 1;
            if (first.value == 0)
            {
                first.print();
                break;
            }
            Q.push(Node(first, 0));
            Q.push(Node(first, 1));
        }
    }
    return 0;
}


F POJ 3126

注意素數的判別不要弄錯,小於等於根號n

//注意判斷素數那裡小於等於根號i
#include<iostream>
#include<set>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;

int M;
bool prime[10005];
int path[10005];
queue<int> Q;

void primebuild()
{
    memset(prime, 0, sizeof(prime));
    for (int i = 1001; i < 10000; i++)
    {
        int temp = floor(sqrt(1.0*i) + 0.5);
        bool fuck = true;
        for (int j = 2; j <= temp; j++)
        {
            if (i % j == 0)
            {
                fuck = false;
                break;
            }
        }
        prime[i] = fuck;
    }
}

int bfs(int a, int b)
{
    memset(path, -1, sizeof(path));
    while (!Q.empty())
    {
        Q.pop();
    }
    path[a] = 0;
    Q.push(a);
    int first;
    while (!Q.empty())
    {
        first = Q.front();
        Q.pop();
        if (first == b)return path[first];
        int p = first % 1000;
        for (int i = 1; i < 10; i++)
        {
            p += 1000;
            if (path[p] < 0 && prime[p])
            {
                Q.push(p);
                path[p] = path[first] + 1;
            }
        }
        p = (first / 1000) * 1000 + (first % 100);
        for (int i = 0; i < 10; i++)
        {
            if (path[p] < 0 && prime[p])
            {
                Q.push(p);
                path[p] = path[first] + 1;
            }
            p += 100;
        }
        p = first - (first % 100) + (first % 10);
        for (int i = 0; i < 10; i++)
        {
            if (path[p] < 0 && prime[p])
            {
                Q.push(p);
                path[p] = path[first] + 1;
            }
            p += 10;
        }
        p = first - (first % 10);
        for (int i = 0; i < 10; i++)
        {
            if (path[p] < 0 && prime[p])
            {
                Q.push(p);
                path[p] = path[first] + 1;
            }
            p++;
        }
    }
    return -1;
}

int main()
{
    primebuild();
    cin >> M;
    while (M--)
    {
        int a, b;
        cin >> a >> b;
        cout << bfs(a, b) << endl;
    }
    return 0;
}


G POJ 3087

模擬題,注意某一狀態第二次出現時剪枝。水題

//純模擬題,注意兩副牌重複交叉一定次數一定會迴圈到開始
#include<iostream>
#include<cstring>
#include<string>
#include<map>
using namespace std;

int M, C;
string a, b, c;
map<string, int> mm;

string change()
{
    string ret = "";
    for (int i = 0; i < (C << 1); i++)
    {
        if (i & 1) ret += a[i>>1];
        else ret += b[i>>1];
    }
    a = ret.substr(0, C);
    b = ret.substr(C, C);
    return ret;
}

int main()
{
    cin >> M;
    for (int kase = 0; kase < M; kase++)
    {
        mm.clear();
        cin >> C >> a >> b >> c;
        cout << kase + 1 << " ";
        int ans = 0;
        while (true)
        {
            string temp = change();
            ans++;
            if (temp == c)break;
            else
            {
                if (mm[temp] == 1)
                {
                    ans = -1;
                    break;
                }
                else
                {
                    mm[temp] = 1;
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}


H POJ 3414

細節上別弄錯。bfs水題

//類的建構函式的形參型別為該類必須用引用
//注意set放結構體的時候必須要過載<
#include<iostream>
#include<queue>
#include<set>
#include<string>
using namespace std;

int a, b, c;

struct State
{
    int la, lb;
    bool ok() { if (la == c || lb == c)return true; return false; }
    int path;
    string way;
    State() :path(-1), la(0), lb(0), way("") {}
};

struct Node
{
    int la, lb;
    Node(State a):la(a.la), lb(a.lb) {}
};

bool operator < (Node a, Node b)
{
    if (a.la != b.la)return a.la < b.la;
    else return a.lb < b.lb;
}

set<Node> S;
queue<State> Q;

int main()
{
    cin >> a >> b >> c;
    State first;
    first.path++;
    Q.push(first);
    bool fuck = false;
    while (!Q.empty())
    {
        first = Q.front();
        Q.pop();
        Node node(first);
        if (S.count(node))continue;
        else S.insert(node);
        if (first.ok())
        {
            cout << first.path << endl;
            cout << first.way;
            fuck = true;
            break;
        }
        else
        {
            first.path++;
            State temp = first;
            if (first.la < a)
            {
                temp.way += "FILL(1)\n";
                temp.la = a;
                Q.push(temp);
            }
            temp = first;
            if (first.lb < b)
            {
                temp.way += "FILL(2)\n";
                temp.lb = b;
                Q.push(temp);
            }
            temp = first;
            if (first.la > 0)
            {
                temp.way += "DROP(1)\n";
                temp.la = 0;
                Q.push(temp);
            }
            temp = first;
            if (first.lb > 0)
            {
                temp.way += "DROP(2)\n";
                temp.lb = 0;
                Q.push(temp);
            }
            temp = first;
            if (first.la < a && first.lb > 0)
            {
                temp.way += "POUR(2,1)\n";
                int cc = a - first.la;
                if (cc > first.lb)
                {
                    temp.la += first.lb;
                    temp.lb = 0;
                }
                else
                {
                    temp.lb -= cc;
                    temp.la = a;
                }
                Q.push(temp);
            }
            temp = first;
            if (first.lb < b && first.la > 0)
            {
                temp.way += "POUR(1,2)\n";
                int cc = b - first.lb;
                if (cc > first.la)
                {
                    temp.lb += first.la;
                    temp.la = 0;
                }
                else
                {
                    temp.la -= cc;
                    temp.lb = b;
                }
                Q.push(temp);
            }
        }
    }
    if (!fuck) cout << "impossible" << endl;
    return 0;
}


I FZU 2150

dfs窮舉組合數+bfs。注意筆誤

//dfs窮舉組合數+bfs暴力
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;

int map[12][12];
int grass[12][12];
int T, n, m;
int px[105], py[105];
int tot;
int fire[3];
int ans;
int dx[] = { -1, 0, 1, 0 };
int dy[] = { 0, 1, 0, -1 };
int visited[12][12];

struct Node
{
    int x, y;
    int path;
    Node() {}
    Node(int x, int y, int path) :x(x), y(y), path(path) {}
};

queue<Node> Q;

void dfs(int cur, int num)
{
    if (cur == 2)
    {
        memcpy(grass, map, sizeof(map));
        memset(visited, 0, sizeof(visited));
        int t = -1;
        Node t1 = Node(px[fire[0]], py[fire[0]], 0), t2 = Node(px[fire[1]], py[fire[1]], 0);
        Q.push(t1);
        Q.push(t2);
        while (!Q.empty())
        {
            Node temp = Q.front();
            Q.pop();
            if (grass[temp.x][temp.y] == 0)continue;
            else
            {
                t = max(t, temp.path);
                grass[temp.x][temp.y] = 0;
                for (int i = 0; i < 4; i++)
                {
                    if (temp.x + dx[i] < 0 || temp.x + dx[i] > n - 1)continue;
                    if (temp.y + dy[i] < 0 || temp.y + dy[i] > m - 1)continue;
                    if (visited[temp.x + dx[i]][temp.y + dy[i]] == 1)continue;
                    Q.push(Node(temp.x + dx[i], temp.y + dy[i], temp.path + 1));
                    visited[temp.x + dx[i]][temp.y + dy[i]] = 1;
                }
            }
        }
        bool fuck = true;
        for (int i = 0; i < n; i++)
        {
            bool cc = true;
            for (int j = 0; j < m; j++)
            {
                if (grass[i][j] == 1)
                {
                    cc = false;
                    break;
                }
            }
            if (!cc)
            {
                fuck = false;
                break;
            }
        }
        if (fuck)
        {
            ans = min(ans, t);
        }
    }
    else
    {
        for (int i = num; i < tot; i++)
        {
            fire[cur] = i;
            dfs(cur + 1, i);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> T;
    for (int kase = 0; kase < T; kase++)
    {
        tot = 0;
        ans = (1 << 30);
        memset(map, 0, sizeof(map));
        memset(px, -1, sizeof(px));
        memset(py, -1, sizeof(py));
        cin >> n >> m;
        char chTmp;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                cin >> chTmp;
                if (chTmp == '#')
                {
                    map[i][j] = 1;
                    px[tot] = i;
                    py[tot] = j;
                    tot++;
                }
                else
                    map[i][j] = 0;
            }
            cin.ignore();
        }
        dfs(0, 0);
        if (ans == (1 << 30))ans = -1;
        cout << "Case " << kase + 1 << ": " << ans << endl;
    }
    return 0;
}


J UVA 11624

注意狀態的先後變化。bfs水題

#include<iostream>
#include<cstring>
#include<string>
#include<queue>
using namespace std;

int T;
int R, C;
int fr, fc;
int map[1005][1005];
int visited[1005][1005];
const int dr[] = { 0, 1, 0, -1 };
const int dc[] = { 1, 0, -1, 0 };

struct Node
{
    int row, col;
    int path;
    bool fire;
    Node() {}
    Node(int row, int col, int path, bool fire) :row(row), col(col), path(path), fire(fire) {}
};

queue<Node> Q;

int main()
{
    cin >> T;
    while (T--)
    {
        while (!Q.empty())
        {
            Q.pop();
        }
        memset(map, -1, sizeof(map));
        memset(visited, 0, sizeof(visited));
        cin >> R >> C;
        char chTmp;
        for (int i = 1; i <= R; i++)
        {
            for (int j = 1; j <= C; j++)
            {
                cin >> chTmp;
                if (chTmp == '#')
                {
                    map[i][j] = -1;
                }
                else
                {
                    if (chTmp == '.')
                    {
                        map[i][j] = 1;
                    }
                    else
                    {
                        if (chTmp == 'F')
                        {
                            map[i][j] = -2;
                            Q.push(Node(i, j, -1, true));
                        }
                        else
                        {
                            map[i][j] = 1;
                            fr = i;
                            fc = j;
                        }
                    }
                }
            }
            cin.ignore();
        }
        Q.push(Node(fr, fc, 0, false));
        bool fuck = true;
        Node first;
        while (!Q.empty())
        {
            first = Q.front();
            Q.pop();
            if (!first.fire)
            {
                for (int i = 0; i < 4; i++)
                {
                    if (first.row + dr[i] < 1 || first.row + dr[i] > R || first.col + dc[i] < 1 || first.col + dc[i] > C)
                    {
                        fuck = false;
                        cout << first.path + 1 << endl;
                        break;
                    }
                    else
                    {
                        if (visited[first.row + dr[i]][first.col + dc[i]] == 0 && map[first.row + dr[i]][first.col + dc[i]] > 0)
                        {
                            visited[first.row + dr[i]][first.col + dc[i]] = 1;
                            Q.push(Node(first.row + dr[i], first.col + dc[i], first.path + 1, false));
                        }
                    }
                }
                if (!fuck)break;
            }
            else
            {
                for (int i = 0; i < 4; i++)
                {
                    if (first.row + dr[i] < 1 || first.row + dr[i] > R || first.col + dc[i] < 1 || first.col + dc[i] > C)continue;
                    if (map[first.row + dr[i]][first.col + dc[i]] > 0 && visited[first.row + dr[i]][first.col + dc[i]] == 0)
                    {
                        Q.push(Node(first.row + dr[i], first.col + dc[i], -1, true));
                        map[first.row + dr[i]][first.col + dc[i]] = -2;
                        visited[first.row + dr[i]][first.col + dc[i]] = 1;
                    }
                }
            }
        }
        if (fuck)cout << "IMPOSSIBLE" << endl;
    }
    return 0;
}


K POJ 3984

本專題最簡單的水題。

#include<iostream>
#include<string>
#include<queue>
using namespace std;

int map[5][5];
int visited[5][5];
const int dr[] = { -1, 0, 1, 0 };
const int dc[] = { 0, -1, 0, 1 };

struct Node
{
    int row, col;
    int path;
    string way;
    Node(int row, int col, int path) :row(row), col(col), path(path) { way = ""; }
};
queue<Node> Q;

int main()
{
    for (int i = 0; i < 5; i++)
        for (int j = 0; j < 5; j++)
            cin >> map[i][j];
    Node first = Node(0, 0, 0);
    first.way = "(0, 0)\n";
    visited[0][0] = 1;
    Q.push(first);
    while (!Q.empty())
    {
        first = Q.front(); Q.pop();
        if (first.row == 4 && first.col == 4)
        {
            cout << first.way;
            break;
        }
        else
        {
            for (int i = 0; i < 4; i++)
            {
                if (first.row + dr[i] < 0 || first.row + dr[i] > 4 || first.col + dc[i] < 0 || first.col + dc[i] > 4)
                {
                    continue;
                }
                else
                {
                    if (map[first.row + dr[i]][first.col + dc[i]] == 0 && visited[first.row + dr[i]][first.col + dc[i]] == 0)
                    {
                        Node temp = first;
                        temp.row += dr[i];
                        temp.col += dc[i];
                        temp.path++;
                        temp.way += "(";
                        temp.way += first.row + dr[i] + 48;
                        temp.way += ", ";
                        temp.way += first.col + dc[i] + 48;
                        temp.way += ")\n";
                        Q.push(temp);
                        visited[first.row + dr[i]][first.col + dc[i]] = 1;
                    }
                }
            }
        }
    }
    return 0;
}


L HDU 1241

紫書例題,八連通圖。水題

#include<iostream>
#include<cstring>
using namespace std;

const int maxn = 105;
const int dr[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

int ans;
int r, c;
int map[maxn][maxn];
int visited[maxn][maxn];
void dfs(int row, int col);

int main()
{
    char chTmp;
    while (cin >> r >> c)
    {
        if (r == 0)break;
        ans = 0;
        memset(map, 0, sizeof(map));
        memset(visited, 0, sizeof(map));
        for (int i = 1; i <= r; i++)
        {
            for (int j = 1; j <= c; j++)
            {
                cin >> chTmp;
                if (chTmp == '@')
                    map[i][j] = 1;
            }
            cin.ignore();
        }
        for (int i = 1; i <= r; i++)
        {
            for (int j = 1; j <= c; j++)
            {
                if (map[i][j] == 1 && visited[i][j] == 0)
                {
                    dfs(i, j);
                    ans++;
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}

void dfs(int row, int col)
{
    visited[row][col] = 1;
    for (int i = 0; i < 8; i++)
    {
        if (row + dr[i] < 1 || row + dr[i] > r || col + dc[i] < 1 || col + dc[i] > c)continue;
        if (map[row + dr[i]][col + dc[i]] == 1 && visited[row + dr[i]][col + dc[i]] == 0)
        {
            dfs(row + dr[i], col + dc[i]);
        }
    }
}


M HDU 1495

和上面某題極其相似。水題。

#include<iostream>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;

int s, n, m;

struct Node
{
    int a, b, c;
    int path;
    Node(int a, int b, int c, int path) :a(a), b(b), c(c), path(path) {}
};

struct State
{
    int a, b, c;
    State() {}
    State(Node x) :a(x.a), b(x.b), c(x.c) {}
};

bool operator < (const State& x, const State& y)
{
    if (x.a != y.a) return x.a < y.a;
    else
    {
        if (x.b != y.b) return x.b < y.b;
        else return x.c < y.c;
    }
}

set<State> S;
queue<Node> Q;

int main()
{        
    while (cin >> s >> n >> m)
    {
        while (!Q.empty())
        {
            Q.pop();
        }
        S.clear();
        if (s == 0)break;
        Node first = Node(s, 0, 0, 0);
        State temp;
        Q.push(first);
        bool fuck = true;
        if (s % 2 == 0)
        while (!Q.empty())
        {
            first = Q.front(); Q.pop();
            temp = State(first);
            int pp[3] = { first.a, first.b, first.c };
            sort(pp, pp + 3);
            if (pp[1] == s / 2 && pp[2] == s / 2)
            {
                cout << first.path << endl;
                fuck = false;
                break;
            }
            if (S.count(temp) == 1)
            {
                continue;
            }
            else
            {
                S.insert(temp);
                if (first.a > 0)
                {
                    if (first.b < n)
                    {
                        Q.push(Node(max(0, first.a - n + first.b), min(n, first.b + first.a), first.c, first.path + 1));
                    }
                    if (first.c < n)
                    {
                        Q.push(Node(max(0, first.a - m + first.c), first.b, min(m, first.c + first.a), first.path + 1));
                    }
                }
                if (first.b > 0)
                {
                    Q.push(Node(first.a + first.b, 0, first.c, first.path + 1));
                    if (first.c < m)
                    {
                        Q.push(Node(first.a, max(0, first.b - m + first.c), min(m, first.c + first.b), first.path + 1));
                    }
                }
                if (first.c > 0)
                {
                    Q.push(Node(first.a + first.c, first.b, 0, first.path + 1));
                    if (first.b < m)
                    {
                        Q.push(Node(first.a, min(n, first.b + first.c), max(0, first.c - n + first.b), first.path + 1));
                    }
                }
            }
        }
        if (fuck)cout << "NO" << endl;
    }
    return 0;
}

N HDU 2612

注意不能用太暴力的方法,不然會MLE/TLE

//一開始的思路是窮舉每個點到Y M的距離, TLE
//改進了一下,打表,兩次BFS求Y\M到每個點的距離,AC
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 205;
const int dr[] = { -1, 0, 1, 0 };
const int dc[] = { 0, -1, 0, 1 };
int r, c;
int map[maxn][maxn];
int visited[maxn][maxn];
int tot = 0;
int kr[maxn*maxn], kc[maxn*maxn];
int yr, yc, mr, mc;
int yk[maxn*maxn], mk[maxn*maxn];

struct Node
{
    int row, col;
    int path;
    Node() {}
    Node(int row, int col, int path) :row(row), col(col), path(path) {}
};
queue<Node> Q;

int main()
{
    char chTmp;
    while (scanf("%d %d\n", &r, &c) != EOF)
    {
        memset(map, -1, sizeof(map));
        for (int i = 1; i <= r; i++)
        {
            for (int j = 1; j <= c; j++)
            {
                cin >> chTmp;
                if (chTmp == '.')
                {
                    map[i][j] = 0;
                }
                else
                {
                    if (chTmp == '@')
                    {
                        map[i][j] = ++tot;
                        kr[tot] = i;
                        kc[tot] = j;
                    }
                    else
                    {
                        if (chTmp == 'Y')
                        {
                            map[i][j] = 0;
                            yr = i;
                            yc = j;
                        }
                        else
                        {
                            if (chTmp == 'M')
                            {
                                map[i][j] = 0;
                                mr = i;
                                mc = j;
                            }
                        }
                    }
                }
            }
            getchar();
        }
        Node temp;
        memset(visited, 0, sizeof(visited));
        memset(yk, -1, sizeof(yk));
        Q.push(Node(yr, yc, 0));
        visited[yr][yc] = 1;
        while (!Q.empty())
        {
            temp = Q.front(); Q.pop();
            if (map[temp.row][temp.col] > 0)
            {
                yk[map[temp.row][temp.col]] = temp.path;
            }
            for (int i = 0; i < 4; i++)
            {
                if (temp.row + dr[i] < 1 || temp.row + dr[i] > r || temp.col + dc[i] < 1 || temp.col + dc[i] > c)continue;
                if (visited[temp.row + dr[i]][temp.col + dc[i]] == 0 && map[temp.row + dr[i]][temp.col + dc[i]] >= 0)
                {
                    visited[temp.row + dr[i]][temp.col + dc[i]] = 1;
                    Q.push(Node(temp.row + dr[i], temp.col + dc[i], temp.path + 1));
                }
            }
        }
        memset(visited, 0, sizeof(visited));
        memset(mk, -1, sizeof(mk));
        Q.push(Node(mr, mc, 0));
        visited[mr][mc] = 1;
        while (!Q.empty())
        {
            temp = Q.front(); Q.pop();
            if (map[temp.row][temp.col] > 0)
            {
                mk[map[temp.row][temp.col]] = temp.path;
            }
            for (int i = 0; i < 4; i++)
            {
                if (temp.row + dr[i] < 1 || temp.row + dr[i] > r || temp.col + dc[i] < 1 || temp.col + dc[i] > c)continue;
                if (visited[temp.row + dr[i]][temp.col + dc[i]] == 0 && map[temp.row + dr[i]][temp.col + dc[i]] >= 0)
                {
                    visited[temp.row + dr[i]][temp.col + dc[i]] = 1;
                    Q.push(Node(temp.row + dr[i], temp.col + dc[i], temp.path + 1));
                }
            }
        }
        int ans = (1 << 30);
        for (int i = 1; i <= tot; i++)
        {
            if (yk[i] == -1 || mk[i] == -1)continue;
            ans = min(ans, yk[i] + mk[i]);
        }
        printf("%d\n", ans * 11);
    }
    return 0;
}