AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

代码笔记_深搜+宽搜

作者: 作者的头像   zqiceberg ,  2020-01-12 04:31:24 ,  所有人可见 ,  阅读 1096


3


6

DFS

AcWing 842. 排列数字

#include <iostream>

using namespace std;

const int N = 10;

int n;
int path[N];
bool st[N];

void dfs(int u)
{
    if (u == n)
    {
        for (int i = 0; i < n; i++) cout << path[i] << ' ';
        puts("");
        return;
    }

    for (int i = 1; i <= n; i++)
    {
        if (!st[i])
        {
            path[u] = i;
            st[i] = true;
            dfs(u + 1);
            //恢复现场
            //path[u] = 0;
            st[i] = false;
        }
    }
}

int main()
{
    cin >> n;

    dfs(0);

    return 0;
}

AcWing 843. n-皇后问题

第一种搜索顺序

#include <iostream>

using namespace std;

const int N = 20;

int n;
char map[N][N];
bool col[N], dg[N * 2], udg[N * 2];

void dfs(int u)
{
    if (u == n)   //搜索到n个皇后
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++) cout << map[i][j];
            puts("");
        }
        puts("");
        return;
    }

    for (int i = 0; i < n; i++)
        if (!col[i] && !dg[u + i] && !udg[n - u + i])
        {
            map[u][i] = 'Q';
            col[i] = dg[u + i] = udg[n - u + i] = true;
            dfs(u + 1);
            col[i] = dg[u + i] = udg[n - u + i] = false;
            map[u][i] = '.';
        }   
}

int main()
{
    cin >> n;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            map[i][j] = '.';

    dfs(0);

    return 0;
}

第二种搜索顺序

#include <iostream>

using namespace std;

const int N = 20;

int n;
char map[N][N];
bool row[N], col[N], dg[N * 2], udg[N * 2];

void dfs(int x, int y, int s)
{
      //扫描完一行,n-1是一列的最后一个位置,y到达n,就代表一行结束
      if (y == n) y = 0, x++;

      //0 ... n-1 行,当x = n,就代表n行都扫描完了
      if (x == n)
      {
          if (s == n)
          {
              for (int i = 0; i < n; i++) puts(map[i]);
              puts("");
          }
          return;
      }

      //不放
      dfs(x, y + 1, s);

      //放
      if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n])
      {
          map[x][y] = 'Q';
          row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
          dfs(x, y + 1, s + 1);
          row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
          map[x][y] = '.';
      }
}

int main()
{
    cin >> n;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            map[i][j] = '.';

    dfs(0, 0, 0);

    return 0;
}

AcWing 1112. 迷宫

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110;

char g[N][N];
bool st[N][N];

int xa, ya, xb, yb;
int n;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

bool dfs(int x, int y)
{   
    if (g[x][y] == '#') return false;   //先要判断这个点是不是"#"
    if (x == ya && y == yb) return true;

    st[x][y] = true;
    for (int i = 0; i < 4; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= n || b < 0 || b >= n) continue;
        if (st[a][b]) continue;

        st[a][b] = true;
        if (dfs(a, b)) return true;
    }

    return false;
}

int main()
{
    int M;
    cin >> M;

    while (M--)
    {
        cin >> n;

        for (int i = 0; i < n; i++) cin >> g[i];
        memset(st, false, sizeof st);

        cin  >> xa >> xb >> ya >> yb;

        if (dfs(xa, xb)) cout << "YES" << endl;
        else cout << "NO" << endl;
    }

    return 0;
}

AcWing 1113. 红与黑

#include <iostream>
#include <cstring>

using namespace std;

const int N = 25;

char g[N][N];
bool st[N][N];
int n, m;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int dfs(int x, int y)
{
    int cnt = 1;

    st[x][y] = true;
    for (int i = 0; i < 4; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= n || b < 0 || b >= m) continue;
        if (g[a][b] != '.') continue;
        if (st[a][b]) continue;

        cnt += dfs(a, b);
    }

    return cnt;
}

int main()
{
    while (cin >> m >> n, n || m)
    {
        for (int i = 0; i < n; i++) cin >> g[i];

        memset(st, 0, sizeof st);

        int x, y;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (g[i][j] == '@')
                    x = i, y = j;

        cout << dfs(x, y) << endl;
    }

    return 0;
}

AcWing 1116. 马走日

#include <iostream>
#include <cstring>

using namespace std;

const int N = 15;

int g[N][N];
bool st[N][N];
int ans;
int n, m, x, y;

int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[] = {1, 2, 2, 1, -1, -2, -2, -1};

void dfs(int x, int y, int cnt)
{
    if (cnt == n * m)
    {
        ans++;
        return ;
    }

    st[x][y] = 1;
    for (int i = 0; i < 8; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= n || b < 0 || b >= m) continue;
        if (st[a][b]) continue;

        st[a][b] = 1;
        dfs(a, b, cnt + 1);
        st[a][b] = 0;
    }
}

int main()
{
    int M;
    cin >> M;

    while (M--)
    {
        memset(st, 0, sizeof st);
        cin >> n >> m >> x >> y;
        ans = 0;

        dfs(x, y, 1);
        cout << ans << endl;
    }

    return 0;
}

AcWing 1117. 单词接龙

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

using namespace std;

const int N = 21;

string word[N];
int g[N][N];
int used[N];
int n;
int ans;

void dfs(string dragon, int last)
{
    ans = max((int)dragon.size(), ans);

    used[last]++;

    for (int i = 0; i < n; i++)
        if (g[last][i] && used[i] < 2)
            dfs(dragon + word[i].substr(g[last][i]), i);

    used[last]--;
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> word[i];
    char start;
    cin >> start;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            string a = word[i], b = word[j];
            for (int k = 1; k < min(a.size(), b.size()); k++)
                if (a.substr(a.size()-k, k) == b.substr(0, k))
                {
                    g[i][j] = k;
                    break;            //两个单词接起来的字符串越短越好
                }
        }

    for (int i = 0; i < n; i++)
        if (word[i][0] == start)
            dfs(word[i], i);  //从word[i]开始搜,当前最后一个单词是i。记一下当前单词是i,判断下一个单词是不是能接

    cout << ans << endl;

    return 0;
}

AcWing 1118. 分成互质组

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 15;

int n;
int p[N];
int group[N][N];
bool st[N];
int ans = N;

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

bool check(int group[], int gc, int i)
{
    for (int j = 0; j < gc; j++)
        if (gcd(p[group[j]], p[i]) > 1)
            return false;

    return true;
}

//搜第g组,当前组里有gc个元素,当前一共搜了tc个元素,这组从start号下标开始搜
void dfs(int g, int gc, int tc, int start)
{
    if (g >= ans) return ;
    if (tc == n) ans = g;

    bool flag = true;
    for (int i = start; i < n; i++)
        if (!st[i] && check(group[g], gc, i))
        {
            st[i] = true;
            group[g][gc] = i;
            dfs(g, gc + 1, tc + 1, i + 1);
            st[i] = false;

            flag = false;
        }

    //新开组    
    if (flag) dfs(g + 1, 0, tc, 0);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i];

    dfs(1, 0, 0, 0); //搜第1组,当前组里有0个元素,当前一共搜了0个元素,这组从0号下标开始搜

    cout << ans << endl;

    return 0;
}

165. 小猫爬山

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 20;

int n, m;
int w[N];
int sum[N];
int ans = N;

void dfs(int u, int k) //搜索第u个小猫,开了k个车
{
    if (k >= ans) return ;//最优性剪枝
    if (k < ans && u == n)
    {
        ans = k;
        return ;
    }

    //可行性剪枝
    for (int i = 0; i < k; i++)
        if (sum[i] + w[u] <= m)
        {
            sum[i] += w[u];
            dfs(u + 1, k);  //搜索下一个,k个车不变
            sum[i] -= w[u];
        }

    //新开一辆车
    sum[k] = w[u];    //sum[k] 指第k+1个车
    dfs(u + 1, k + 1);
    sum[k] = 0;
}

int main()
{
    cin >> n >> m;
    for (int i= 0; i < n; i++)  cin >> w[i];

    sort(w, w + n);
    reverse(w, w + n);

    dfs(0, 0);  //从第0号开始搜,已经搜了0个

    cout << ans << endl;

    return 0;
}

AcWing 166. 数独

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

using namespace std;

const int N = 9, M = 1 << N;

//打表
//ones[M]快速的求出来状态里有多少个1,map[]log2k
int ones[M], map[M];
int row[N], col[N], cell[3][3];
char str[100];

void init()
{
    //初始化每一位都是1,1代表可以用,1-9都可以用
    for (int i = 0; i < N; i++)
        row[i] = col[i] = (1 << N) - 1;

    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            cell[i][j] = (1 << N) - 1;
}

//辅助函数
//当前在x,y是把t填上,还是删掉(填就是dfs,删掉就是恢复现场的过程)
//1表示能用,0表示不能用
void draw(int x, int y, int t, bool is_set)
{
    if (is_set) str[x * N + y] = '1' + t; //t是0-8
    else str[x * N + y] = '.';

    int v = 1 << t;
    if (!is_set) v = -v;   //如果是清空操作,取反

    row[x] -= v;
    col[y] -= v;
    cell[x / 3][y / 3] -= v; 
}

int lowbit(int x)
{
    return x & -x;
}

int get(int x, int y)
{
    //哪一个数可以用
    return row[x] & col[y] & cell[x / 3][y / 3]; 
}

bool dfs(int cnt)
{
    if (!cnt) return true;   //当前没有宫格了,就找到合法方案

    int minv = 10;
    int x, y;
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            if (str[i * N + j] == '.')
            {
                int state = get(i, j);
                if (ones[state] < minv)    //每个二进制数里1的个数
                {
                    minv = ones[state];
                    x = i, y = j;
                }
            }

    //循环完,xy存的是分支数量最少的格子
    //先看下这个格子能枚举哪个数
    int state = get(x, y);
    for (int i = state; i; i -= lowbit(i))
    {
        int t = map[lowbit(i)];  //lowbit(i)返回2的k次方,map一下,把2的k次方映射成k(1代表这个数可以填,map映射给t)
        draw(x, y, t, true);
        if (dfs(cnt - 1)) return true; //dfs下一层
        draw(x, y, t, false);
    }

    return false;
}

int main()
{
    for (int i = 0; i < N; i++) map[1 << i] = i;//2的i次幂作为下标,存的值为i
    for (int i = 0; i < 1 << N; i++)
        for (int j = 0; j < N; j++)
            ones[i] += i >> j & 1;   //每个数二进制表示有多少个1

    while (cin >> str, str[0] != 'e')
    {
        init();

        int cnt = 0;
        for (int i = 0, k = 0; i < N; i++)
            for (int j = 0; j < N; j++, k++)
                if (str[k] != '.')
                {
                    int t = str[k] - '1';  //先看下数字是多少
                    draw(i, j, t, true);   //在这个点填上t
                }
                else cnt++;                //否则就是空格

        dfs(cnt);

        puts(str);
    }

    return 0;
}

AcWing 167. 木棒

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

using namespace std;

const int N = 70;

int n;
int w[N], sum, length;
bool st[N];

bool dfs(int u, int s, int start)
{
    if (u * length == sum) return true;
    if (s == length) return dfs(u + 1, 0, 0);

    //i从start开始枚举
    for (int i = start; i < n; i++)
    {
        if (st[i]) continue;
        if (s + w[i] > length) continue;

        st[i] = true;
        if (dfs(u, s + w[i], i + 1)) return true;
        st[i] = false;

        //如果当前大棍的第一个小棍就失败的话,就return
        if (!s) return false;

        //如果当前大棍的最后一个小棍失败的话,就return
        if (s + w[i] == length) return false;

        //当前长度的失败了,等长的都不要试了
        int j = i;
        while (j < n && w[j] == w[i]) j++;
        i = j - 1;
    }

    return false;
}

int main()
{
    while (cin >> n, n)
    {
        memset(st, 0, sizeof st);
        sum = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> w[i];
            sum += w[i];
        }

        //优化搜索顺序
        sort(w, w + n);
        reverse(w, w + n);

        length = 1;
        while (true)
        {
            if (sum % length == 0 && dfs(0, 0, 0)) //枚举每一根大棍,每根长度为0,从0开始枚举
            {
                cout << length << endl;
                break;
            }
            length++;
        }
    }

    return 0;
}#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 70;

int n;
int w[N], sum, length;
bool st[N];

bool dfs(int u, int s, int start)
{
    if (u * length == sum) return true;
    if (s == length) return dfs(u + 1, 0, 0);

    //i从start开始枚举
    for (int i = start; i < n; i++)
    {
        if (st[i]) continue;
        if (s + w[i] > length) continue;

        st[i] = true;
        if (dfs(u, s + w[i], i + 1)) return true;
        st[i] = false;

        //如果当前大棍的第一个小棍就失败的话,就return
        if (!s) return false;

        //如果当前大棍的最后一个小棍失败的话,就return
        if (s + w[i] == length) return false;

        //当前长度的失败了,等长的都不要试了
        int j = i;
        while (j < n && w[j] == w[i]) j++;
        i = j - 1;
    }

    return false;
}

int main()
{
    while (cin >> n, n)
    {
        memset(st, 0, sizeof st);
        sum = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> w[i];
            sum += w[i];
        }

        //优化搜索顺序
        sort(w, w + n);
        reverse(w, w + n);

        length = 1;
        while (true)
        {
            if (sum % length == 0 && dfs(0, 0, 0)) //枚举每一根大棍,每根长度为0,从0开始枚举
            {
                cout << length << endl;
                break;
            }
            length++;
        }
    }

    return 0;
}

AcWing 168. 生日蛋糕

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 25, INF = 1e9;

int n, m;
int minv[N], mins[N];
int R[N], H[N];
int ans = INF;

void dfs(int u, int v, int s)//从第u层开始,当前体积v,当前面积s
{
    if (v + minv[u] > n) return ;  //体积大于n,剪枝
    if (s + mins[u] >= ans) return ; //面积比当前ans大,剪枝
    if (s + 2 * (n - v) / R[u + 1] >= ans) return ; //最优性剪枝 算法进阶指南P108

    if (!u)
    {
        if (v == n) ans = s;
        return ;
    }

    for (int r = min(R[u + 1] - 1, (int)sqrt(n - v)); r >= u; r--)
        for (int h = min(H[u + 1] - 1, (n - v) / r / r); h >= u; h--)
        {
            int t = 0;
            if (u == m) t = r * r; //最后一层,算一下封盖的面积

            R[u] = r, H[u] = h;
            dfs(u - 1, v + r * r * h, s + 2 * r * h + t);//从第u-1层开始,当前体积v+r*r*h,当前面积s+2*r*h+t
        }
}

int main()
{
    cin >> n >> m;

    //打表处理每一行最小的体积和面积,自底向上,每一层严格小于上一层的半径和高度
    for (int i = 1; i <= m; i++)
    {
        minv[i] = minv[i - 1] + i * i * i;    //体积:i*i  *i
        mins[i] = mins[i - 1] + 2 * i * i;    //面积:2*i  *i
    }

    R[m + 1] = H[m + 1] = INF;

    dfs(m, 0, 0);//从第m层开始,当前体积和面积都是0

    cout << ans << endl;

    return 0;
}

BFS

AcWing 844. 走迷宫

用数组

#include <iostream>
#include <cstring>

using namespace std;

typedef pair<int, int> PII;

const int N = 200;

int n, m;
int g[N][N];
int d[N][N];
PII q[N * N], Prev[N][N];

int bfs()
{
    int hh = 0, tt = 0;
    q[0] = {0, 0};

    memset(d, -1, sizeof(d));

    d[0][0] = 0;
    //四个方向的向量
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    while (hh <= tt)
    {
        PII t = q[hh++];
        for (int i = 0; i < 4; i++)
        {   int x = t.first + dx[i], y = t.second + dy[i];
            //if (x >= 0 && x < n && y >= 0 && y < n && g[x][y] == 0 && d[x][y] == -1)  打错字母了
            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1) 
            {
                d[x][y]= d[t.first][t.second] + 1;
                Prev[x][y] = t;
                q[++tt] = {x, y};
            }
        }
    }

/*    
    int x = n - 1, y = m - 1;
    while (x || y)
    {
        cout << x << ' ' << y << endl;
        PII t = Prev[x][y];
        x = t.first, y = t.second;
    }
*/  
    return d[n - 1][m - 1];
}

int main()
{
    cin >> n >> m;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> g[i][j];

    cout << bfs() << endl;

    /*
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%3d", d[i][j]);
        cout << endl;
    }
    */

    return 0;
}

用queue写

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

using namespace std;

const int N = 110;

typedef pair<int, int> PII;

int n, m;
int g[N][N], d[N][N];

int bfs()
{
    queue< pair<int, int> > q;
    memset(d, -1, sizeof(d));
    d[0][0] = 0;
    q.push({0, 0});

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
    while (q.size())
    {
        PII t = q.front();
        q.pop();

        for (int i = 0; i < 4; i++)
        {
            int x = t.first + dx[i], y = t.second + dy[i];
            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second] + 1;
                q.push({x, y});
            }
        }
    }

    return d[n - 1][m -1];
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> g[i][j];

    cout << bfs() << endl;

    return 0;
}

AcWing 845. 八数码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <bits/stdc++.h>

using namespace std;

int bfs(string start)
{
    string end = "12345678x";

    queue<string> q;
    unordered_map<string, int> d;
    q.push(start);    
    d[start] = 0;

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    while (q.size())
    {
        string t = q.front();
        q.pop();
        int dis = d[t];

        if (t == end) return d[t];

        int k = t.find('x');
        int x = k / 3, y = k % 3;

        for (int i = 0; i < 4; i++)
        {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < 3 && b >= 0 && b < 3)
            {
                swap(t[k], t[a * 3 + b]);

                if (!d.count(t))  //第一次出现
                {
                    q.push(t);
                    d[t] = dis + 1;   
                }

                swap(t[k], t[a * 3 + b]);  //一个方向尝试完,要复原一下,尝试下一个方向
            }
        }
    }

    return -1;
}

int main()
{
    string start, c;

    for (int i = 0; i < 9; i++)
    {
        cin >> c;
        start += c;
    }

    cout << bfs(start) << endl;

    return 0;
}

AcWing 1097. 池塘计数

#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int > PII;

const int N = 1010, M = N * N;

PII q[M];
char g[N][N];
bool st[N][N];
int n, m;

void bfs(int xx, int yy)
{
    //队列初始化
    int hh = 0, tt = 0;
    q[0].first = xx, q[0].second = yy;
    st[xx][yy] = true;

    while (hh <= tt)
    {
        PII t = q[hh++];   //取队头,数组模拟队列   

        for (int i = t.first - 1; i <= t.first + 1; i++)
            for (int j = t.second - 1; j <= t.second + 1; j++)
            {
                if (i < 0 || i >= n || j < 0 || j >= m) continue;
                if (i == t.first && j == t.second) continue;   //中间那块挖掉
                if (g[i][j] == '.') continue;
                if (g[i][j] == 'W' && st[i][j]) continue;

                ++tt;
                q[tt].first = i, q[tt].second = j;
                st[i][j] = true;
            }
    }
}

int main()
{
    cin >> n >> m;

    for (int i = 0; i < n; i++)
    {
        getchar();
        for (int j = 0; j < m; j++) scanf("%c", &g[i][j]);
    }

    int cnt = 0;    
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
        {
            if (!st[i][j] && g[i][j] == 'W')  //是一个新的连通块,就BFS进去
            {
                cnt++;
                bfs(i, j);
            }
        }

    printf("%d\n", cnt);

    return 0;
}

AcWing 1098. 城堡问题

#include <iostream>
#include <algorithm>
#include <fstream>

#define x first
#define y second

using namespace std;

const int N = 55, M = N * N;

typedef pair<int, int> PII;

int g[N][N];
bool st[N][N];
PII q[M];

int n, m;

int dx[4] = {0, -1, 0, 1}, dy[4] = {-1, 0, 1, 0};

int idx, f[M];  //连通块编号,连通块的面积
int g_of_idx[N][N]; //记录每个方格属于哪个连通块
int max_area; //记录最大面积
int max_i = -1, max_j = -1;
char max_dir;
string dir = "WNES";

int bfs(int sx, int sy)
{   
    int area = 0;
    int hh = 0, tt = 0;   //模板hh = 0, tt = -1; 此处默认有一个start结点,tt = 0
    q[0].x = sx, q[0].y = sy;
    st[sx][sy] = true;

    idx++;       //每一个新队列,产生一个新的连通块

    while (hh <= tt)
    {
        area++;
        PII t = q[hh++];

        g_of_idx[t.x][t.y] = idx;   //标记这个方块属于哪个房间

        for (int i = 0; i < 4; i++)
        {
            int a = t.x + dx[i], b = t.y + dy[i];

            //越界,被遍历过,continue
            if (a < 0 || a >= n || b < 0 || b >= m) continue;
            if (st[a][b]) continue;

            //这个方格是墙,就continue
            if (g[t.x][t.y] >> i & 1) continue;

            //入队
            ++tt;
            q[tt].x = a, q[tt].y = b;
            st[a][b] = true;
        }
    }

    f[idx] = area; //记录这个编号连通块的面积,记录在f[]里面

    return  area;
}   

int main()
{
    //freopen("P1457_4.in", "r", stdin);

    scanf("%d%d", &m, &n);

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            scanf("%d", &g[i][j]);

    int area = 0, cnt = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
        {
            if (!st[i][j])
            {
                area = max(area, bfs(i, j));
                cnt++;
            }
        }

    printf("%d\n%d\n", cnt, area);

    for (int i = 0; i < n; i++)
        for (int j = m - 1; j >= 0; j--)
            for (int k = 1; k <= 2; k++)  //遍历每个方格的北面和东面,是否是墙,可以推倒
            {
                if ((g[i][j] >> k & 1) != 1) continue; //当前的方格不是墙,就要continue

                int tx = i + dx[k], ty = j + dy[k];
                if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;

                if (g_of_idx[i][j] == g_of_idx[tx][ty]) continue;

                int sum_area = f[g_of_idx[i][j]] + f[g_of_idx[tx][ty]];
                if (sum_area > max_area)
                {
                    max_area = sum_area;
                    max_i = i;
                    max_j = j;
                    max_dir = dir[k];
                }
                else if (sum_area == max_area)
                {
                    //有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。
                    if ((j == max_j && i > max_i) || (i == max_i && j < max_j))
                    {
                        max_area = sum_area;
                        max_i = i;
                        max_j = j;
                        max_dir = dir[k];
                    }

                }
            }

    printf("%d\n", max_area);
    printf("%d %d %c\n", max_i+1, max_j+1, max_dir);  //下标起始问题

    return 0;
}

AcWing 1106. 山峰和山谷

#include <iostream>
#include <algorithm>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 1010, M = N * N;

int h[N][N];
bool st[N][N];
PII q[M];
int n;

void bfs(int sx, int sy, bool &have_higher, bool &have_lower)
{
    int hh = 0, tt = 0;
    q[tt] = {sx, sy};
    st[sx][sy] = true;

    while (hh <= tt)
    {
        PII t = q[hh++];

        for (int i = t.x - 1; i <= t.x + 1; i++)
            for (int j = t.y - 1; j <= t.y + 1; j++)
            {
                if (i == t.x && j == t.y) continue;

                if (i < 0 || i >= n || j < 0 || j >= n) continue;
                if (h[i][j] != h[t.x][t.y])
                {
                    if (h[i][j] > h[t.x][t.y]) have_higher = true;
                    else have_lower = true;
                }
                else
                {
                    if (st[i][j]) continue;

                    q[++tt] = {i, j};
                    st[i][j] = true;
                }
            }
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> h[i][j];

    int peek = 0, valley = 0;        
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (!st[i][j])       
            {
                bool have_higher = false, have_lower = false;
                bfs(i, j, have_higher, have_lower);

                if (!have_higher) peek++;   //用!have_higher的写法,省去了分支判断
                if (!have_lower) valley++;
            }

    cout << peek << ' ' << valley << endl;

    return 0;
}

AcWing 1076. 迷宫问题

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

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 1010, M = N * N;

int n;
int g[N][N];
PII q[M];
PII pre[N][N];

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void bfs(int sx, int sy)
{
    int hh = 0, tt = 0;
    q[tt] = {sx, sy};

    memset(pre, -1, sizeof pre);
    pre[sx][sy] = {0, 0};
    while (hh <= tt)
    {
        PII t = q[hh++];

        for (int i = 0; i < 4; i++)
        {
            int a = t.x + dx[i], b = t.y + dy[i];
            if (a < 0|| a >= n || b < 0 || b >= n) continue;

            if (g[a][b]) continue;
            if (pre[a][b].x != -1) continue;

            q[++tt] = {a, b};
            pre[a][b] = t;
        }
    }

}


int main()
{
    cin >> n;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            scanf("%d", &g[i][j]);

    bfs(n - 1, n - 1);

    PII end = {0, 0};
    while (true)
    {
        printf("%d %d\n", end.x, end.y);
        if (end.x == n - 1 && end.y == n - 1) break;
        end = pre[end.x][end.y];
    }

    return 0;
}

AcWing 188. 武士风度的牛

#include <iostream>
#include <cstring>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 160, M = N * N;
char g[N][N];
int dis[N][N];
PII q[M];
int n, m;

int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
//也可以这样写
//int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2};
//int dy[] = {1, 2, 2, 1, -1, -2, -2, -1};

int bfs()
{
    int sx, sy;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            if (g[i][j] == 'K') sx = i, sy = j;

    int hh = 0, tt = 0;
    q[tt] = {sx, sy};

    memset(dis, -1, sizeof dis);
    dis[sx][sy] = 0;

    while (hh <= tt)
    {
        PII t = q[hh++];

        for (int i = 0; i < 8; i++)
        {
            int a = t.x + dx[i], b = t.y + dy[i];
            if (a < 0 || a >= n || b < 0 || b >= m) continue;
            if (dis[a][b] != -1) continue;

            if (g[a][b] == 'H') return dis[t.x][t.y] + 1;

            //入队操作
            q[++tt] = {a, b};
            dis[a][b] = dis[t.x][t.y] + 1;
        }
    }

    return -1;
}

int main()
{
    cin >> m >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> g[i][j];

    cout << bfs() << endl;

    return 0;
}

AcWing 1100. 抓住那头牛

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

using namespace std;

const int N = 2e5 + 10;

int n, k;
int dist[N];
int q[N];

int bfs()
{
    int hh = 0, tt = 0;
    q[0] = n;

    memset(dist, -1, sizeof dist);
    dist[n] = 0;

    while (hh <= tt)
    {   
        int t = q[hh++];

        if (t == k) return dist[t];

        if (t + 1 <= N && dist[t + 1] == -1) 
        {   
            dist[t+1] = dist[t] + 1;
            q[++tt] = t + 1;
        }
        if (t - 1 >= 0 && dist[t - 1] == -1)
        {
            dist[t-1] = dist[t] + 1;
            q[++tt] = t - 1;
        }
        if (t * 2 <= N && dist[t * 2] == -1)
        {
            dist[t * 2] = dist[t] + 1;
            q[++tt] = t * 2;
        }
    }

    return -1;
}

int main()
{
    cin >> n >> k;

    cout << bfs() << endl;

    return 0;
}

2 评论


用户头像
就是要AC   2021-05-16 20:57         踩      回复

收藏了,棒


用户头像
潘瑞杰   2020-01-12 16:41         踩      回复

棒!


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息