zoukankan      html  css  js  c++  java
  • 搜索

    E - The Morning after Halloween

     UVA - 1601

    https://blog.csdn.net/qq_29169749/article/details/51420097

    这里有双向bfs板,注意双向是搜索一层,而不是一个点。

    这个提的意思是有小于三个小鬼,编号abc,他们要到ABC去,然后求最少的步数,不能够两个小鬼到一个点,也不可以一步是两个小鬼互交换位置。

    首先这个图不连通的地方很多,我们可以把它提出来,编号,自己建一个树来记录小鬼可以移动的 位置。小鬼可以不动和上下左右动(重点看一下那个提出来建图的过程)

    然后提出来之后进行bfs来求出小鬼最小的移动次数。如果没有三个小鬼就自己在添到三个小鬼,要不然要写三个bfs来分别求一个,两个,三个小鬼的情况,然后把那个小鬼连的边就是终点,不影响结果。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cstdlib>
    #include<cctype>
    using namespace std;
    const int maxm = 20;
    const int maxm1 = 150;
    const int dx[] = {-1,1,0,0,0};
    const int dy[] = {0,0,-1,1,0};
    char maze[maxm][maxm];
    int n, m, k;
    int G[maxm1][5];
    int deg[maxm1];
    int cnt;
    int s[3], e[3];
    struct node{
        int a, b, c;
        int steps;
    };
    bool check(int a, int b, int ea, int eb){
        return ea == eb || (a == eb && b == ea);
    }
    queue<node> q;
    int visit[maxm1][maxm1][maxm1];
    int bfs(){
        memset(visit,0,sizeof(visit));
        while(!q.empty()) q.pop();
        node start, pre, temp;
        start.a = s[0], start.b = s[1], start.c = s[2];
        start.steps = 0;
        q.push(start);
        while(!q.empty()){
            pre = q.front();
            q.pop();
            if(pre.a == e[0] && pre.b == e[1] && pre.c == e[2]) return pre.steps;
            for(int i = 0; i < deg[pre.a]; i++) {
                        int na = G[pre.a][i];
                for(int j = 0; j < deg[pre.b]; j++) {
                        int nb = G[pre.b][j];
                        if(check(pre.a, pre.b, na, nb)) continue;
                    for(int k = 0; k < deg[pre.c]; k++){
                        int nc = G[pre.c][k];
                        if(check(pre.a,pre.c,na,nc) || check(pre.b,pre.c,nb,nc)) continue;
                        temp.a = na;
                        temp.b = nb;
                        temp.c = nc;
                        temp.steps = pre.steps + 1;
                        if(!visit[na][nb][nc]) q.push(temp);
                        visit[na][nb][nc] = 1;
                    }
                }
            }
    
        }
    return -1;
    }
    int main()
    {
        while(~scanf("%d%d%d", &n, &m, &k)){
            if(n == 0 && m == 0 && k == 0) break;
            getchar();
            for(int i = 0; i < m; i++)  fgets(maze[i], 20, stdin);
            cnt = 0;
            int x[maxm1], y[maxm1];
            int id[maxm1][maxm1];
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    if(maze[i][j] != '#'){
                        x[cnt] = i;
                        y[cnt] = j;
                        id[i][j] = cnt;
                        if(islower(maze[i][j])) s[maze[i][j] - 'a'] = cnt;
                        if(isupper(maze[i][j])) e[maze[i][j] - 'A'] = cnt;
                        cnt++;
                    }
                }
            }
    
            for(int i = 0; i < cnt; i++){
                deg[i] = 0;
                for(int j = 0; j < 5; j++){
                    int tx = x[i] + dx[j], ty = y[i] + dy[j];
                    if(maze[tx][ty] != '#') {
                        G[i][deg[i]++] = id[tx][ty];
                    }
                }
            }
            if (k <= 2){deg[cnt] = 1; G[cnt][0] = cnt; s[2] = e[2] = cnt++;}
            if (k <= 1){deg[cnt] = 1; G[cnt][0] = cnt; s[1] = e[1] = cnt++;}
            printf("%d
    ", bfs());
        }
        return 0;
    }

     http://codeforces.com/contest/448/problem/C dfs分治

    刷围墙

    每个板子宽度相同,高度不同,刷一次可以横着刷一行或者一竖(宽度为一)

    https://www.cnblogs.com/fu3638/p/9892300.html  分治法dfs

    https://blog.csdn.net/qcwdytx/article/details/38019303 dp法

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxm = 1e5 + 5;
    const int inf = 1e9 + 7;
    int n;
    int a[maxm];
    
    int dfs(int l, int r, int h) {
    if(l == r) return 1;
    int hh = inf;
    for(int i = l; i <= r; i++) {
        hh = min(hh, a[i]);
    }
    int sum = hh - h;
    for(int i = l; i <= r; i++) {
        if(a[i] == hh) continue;
        int j = i;
        while(a[j + 1] > hh && j + 1 <= r) j++;
        sum += dfs(i, j, hh);
        i = j;
    }
    return min(r - l + 1, sum);
    
    }
    
    int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    printf("%d
    ", dfs(1, n, 0));
    }
  • 相关阅读:
    go学习中的零散笔记
    git reset --hard与git reset --soft的区别
    php必学必会
    gdb 解core
    php学习
    高仿京东到家APP引导页炫酷动画效果
    RxHttp
    SVN回滚文件
    遍历枚举
    python3 多线程
  • 原文地址:https://www.cnblogs.com/downrainsun/p/10449537.html
Copyright © 2011-2022 走看看