[kuangbin带你飞]专题一 简单搜索 java题解

kuangbin带你飞:起飞~

1. POJ 1321 棋盘问题

原题链接:棋盘问题
思路:八皇后变形,递归回溯即可

import java.util.Scanner;

public class Main {
    static int[][] map;
    static boolean[] vis;
    static int count, n, k, sum;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            n = sc.nextInt();
            k = sc.nextInt();
            if (n == -1 && k == -1) {
                break;
            }
            map = new int[n][n];
            vis = new boolean[n];
            for (int i = 0; i < n; i++) {
                String s = sc.next();
                for (int j = 0; j < n; j++) {
                    if (s.charAt(j) == '.') {
                        map[i][j] = 0;
                    } else {
                        map[i][j] = 1;
                    }
                }
            }
            count = 0;
            sum = 0;
            find(0);
            System.out.println(count);
        }
    }

    private static void find(int row) {
        if (sum == k) {
            count++;
            return;
        } else if (row == n) {
            return;
        }
        for (int col = 0; col < n; col++) {
            if (map[row][col] == 1 && !vis[col]) {
                vis[col] = true;
                sum++;
                find(row + 1);
                vis[col] = false;
                sum--;
            }
        }
        find(row + 1);//因为k<=n,所以要迭代加深
    }
}

2. POJ 2251 Dungeon Master

原题链接:Dungeon Master
思路:三维BFS 模板题

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    static class Me {
        int x, y, z, step;
        Me(int z,int x,int y,int step){
            this.z=z;
            this.x=x;
            this.y=y;
            this.step=step;
        }
    }

    static char[][][] map;
    static boolean[][][] vis;
    static int[] dx = {0, 1, 0, -1, 0, 0};
    static int[] dy = {1, 0, -1, 0, 0, 0};
    static int[] dz = {0, 0, 0, 0, -1, 1};
    static int L, R, C, sx, sy, sz;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            L = sc.nextInt();
            R = sc.nextInt();
            C = sc.nextInt();
            if (L == 0 && R == 0 && C == 0) {
                break;
            }
            map = new char[L][R][C];
            vis = new boolean[L][R][C];
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < R; j++) {
                    map[i][j] = sc.next().toCharArray();
                }
            }
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < R; j++) {
                    for (int k = 0; k < C; k++) {
                        if (map[i][j][k] == 'S') {
                            sz = i;
                            sx = j;
                            sy = k;
                        }
                    }
                }
            }

            BFS();
        }

    }

    private static void BFS() {
        Queue<Me> q = new ArrayDeque<Me>();
        Me me = new Me(sz,sx,sy,0);
        q.offer(me);
        vis[me.z][me.x][me.y] = true;
        while (!q.isEmpty()) {
            me = q.poll();

            if (map[me.z][me.x][me.y] == 'E') {
                System.out.printf("Escaped in %d minute(s).\n", me.step);
                return;
            }
            for (int i = 0; i < 6; i++) {

                int nz = me.z + dz[i];
                int nx = me.x + dx[i];
                int ny = me.y + dy[i];
                if (nz >= 0 && nz < L && nx >= 0 && nx < R && ny >= 0 && ny < C && map[nz][nx][ny] != '#' && !vis[nz][nx][ny]) {
                    Me my=new Me(nz,nx,ny,me.step+1);
                    vis[my.z][my.x][my.y] = true;
                    q.offer(my);
                }
            }
        }
        System.out.println("Trapped!");
    }

}

3. POJ 3278 Catch That Cow

原题链接:Catch That Cow
思路:如果农民在前牛在后,只能一步一步挪过去
如果农民在后牛在前,就是一维的BFS

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int K = sc.nextInt();
        if (N > K) {
            System.out.println(N - K);
            return;
        }
        Queue<Integer> q = new ArrayDeque<Integer>();
        int[] step = new int[1000000];
        Arrays.fill(step, Integer.MAX_VALUE/2);
        step[N] = 0;
        q.offer(N);
        while (!q.isEmpty()) {
            int temp = q.poll();
            if(temp==K){
                System.out.println(step[K]);
                return;
            }
            int[] next = new int[3];
            next[0] = temp + 1;
            next[1] = temp - 1;
            next[2] = temp * 2;
            for (int i = 0; i < 3; i++) {
                if (next[i] >= 0 && next[i] <= 100000) {
                    int d = step[next[i]];
                    if (d > step[temp] + 1) {
                        step[next[i]] = step[temp] + 1;

                        q.offer(next[i]);
                    }
                }
            }
        }
    }
}

4 .POJ 3279 Fliptile

原题链接:Fliptile,但是要记录最小翻转次数的开关矩阵
思路:类似于熄灯问题

import java.util.Scanner;

public class Main {
    static int n, m, min = Integer.MAX_VALUE / 2;
    //矩阵,开关,翻转中的矩阵,开关情况的记录
    static int[] map, res, mapBack, resBack;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        map = new int[n];
        res = new int[n];
        mapBack = new int[n];
        resBack = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int num = sc.nextInt();
                map[i] = setNum(map[i], j, num);
            }
        }
        //枚举第一行的开关
        for (int i = 0; i < (1 << m); i++) {
            int temp = i;
            mapBack = map.clone();
            for (int row = 0; row < n; row++) {
                res[row] = temp;
                for (int col = 0; col < m; col++) {
                    if (getNum(temp, col) == 1) {
                        mapBack[row] = file(mapBack[row], col);
                        if (col > 0) {
                            mapBack[row] = file(mapBack[row], col - 1);
                        }
                        if (col < m - 1) {
                            mapBack[row] = file(mapBack[row], col + 1);
                        }
                    }
                }
                //次行的情况等于这一行开关的异或
                if (row < n - 1) {
                    mapBack[row + 1] ^= temp;
                }
                //要使次全0,次行开关应该同此行相同
                temp = mapBack[row];
            }
            //矩阵满足条件,记录最小值与对应开关矩阵
            if (mapBack[n - 1] == 0) {
                if (min > getSum()) {
                    min = getSum();
                    resBack = res.clone();
                }
            }
        }
        if (min == Integer.MAX_VALUE / 2) {
            System.out.println("IMPOSSIBLE");
        } else {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    System.out.print(getNum(resBack[i], j) + " ");
                }
                System.out.println();
            }
        }
    }

    //获取翻转次数
    private static int getSum() {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (getNum(res[i], j) == 1) {
                    sum += 1;
                }
            }
        }
        return sum;
    }

    //把x的i位取反
    private static int file(int x, int i) {
        return x ^ (1 << i);
    }

    //获取x的i位数字
    private static int getNum(int x, int i) {
        return (x >> i) & 1;

    }

    //把x的i位设为num
    private static int setNum(int x, int i, int num) {
        if (num == 0) {
            return x & (~(1 << i));
        } else {
            return x | (1 << i);
        }
    }
}

5. POJ 1426 Find The Multiple

原题链接:Find The Multiple
思路:最高位必然是1,然后搜索之后的每一位0或1,直到对num取余为0.应该是数据很弱,只用long最大19位DFS可以ac,但是BFS就是超时,不知道为什么。

import java.util.Scanner;
public class Main {
    static int n;
    static boolean flag;
    static void dfs(int idx,long cur) {//idx当前是几位数,cur当前枚举的数,flag表示找到没有
        if(idx > 19 || flag)
            return;
        if(cur % n == 0) {
            flag = true;
            System.out.println(cur);
            return;
        }
        dfs(idx + 1,cur * 10);
        dfs(idx + 1,cur * 10 + 1);
    }
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        while(cin.hasNext()) {
            n = cin.nextInt();
            if(n == 0)
                break;
            flag = false;
            dfs(1,1L);
        }
    }
}

6. POJ 3126 Prime Path

原题链接:Prime Path
思路:先筛出4位质数,在BFS探索每位数字的变化。

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.Scanner;


public class Main {
    static int a, b;
    static boolean is_prime[] = new boolean[10010];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sieve();//筛出素数
        for (int i = 0; i < n; i++) {
            a = sc.nextInt();
            b = sc.nextInt();
            bfs();

        }
    }

    private static void bfs() {
        int[] step = new int[10010];
        Arrays.fill(step,Integer.MAX_VALUE);
        Queue<Integer> q = new ArrayDeque<Integer>();
        step[a] = 0;
        q.offer(a);
        while (!q.isEmpty()) {
            int temp = q.poll();
            int t=temp;//用于取数
            if (temp == b) {
                System.out.println(step[b]);
            }
            int[] num=new int[4];//取出每位数
            for (int i = 3; i >-1 ; i--) {
                int val=t%10;
                num[i]=val;
                t/=10;
            }
            for (int i = 0; i < 4; i++) {
                int val=num[i];//对没位数取变化
                for (int j = 0; j < 10; j++) {
                    if (i==0&j==0){//去除前导0
                        continue;
                    }
                    num[i]=j;
                    int next=num[0]*1000+num[1]*100+num[2]*10+num[3];
                    if (is_prime[next]&&step[next]>step[temp]+1){
                        step[next]=step[temp]+1;
                        q.offer(next);
                    }
                }
                num[i]=val;//将数还原
            }
        }
		System.out.println("Impossible");
    }

    private static void sieve() {//埃氏筛,遍历到素数就去除这个素数的倍数
        Arrays.fill(is_prime, true);
        is_prime[0] = false;
        is_prime[1] = false;
        for (int i = 2; i < 10010; i++) {
            if (is_prime[i]) {
                for (int j = 2 * i; j < 10010; j += i) {
                    is_prime[j] = false;
                }
            }
        }
    }

}

7. POJ 3087 Shuffle’m Up

原题链接:Shuffle’m Up
思路:简单模拟,失败条件是洗出的两套牌和开始状态一样。注意java中String的比较不能用==,StringBuffer与String也不能直接比较

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        for (int p = 1; p <= N; p++) {
            int len = sc.nextInt();
            String s1 = sc.next();
            String s2 = sc.next();
            String s12 = sc.next();
            String ss1 = new String(s1);
            String ss2 = new String(s2);
            StringBuffer bf;
            boolean flag = true;
            int step = 0;
            do {
                step++;
                char[] c1 = ss1.toCharArray();
                char[] c2 = ss2.toCharArray();
                bf = new StringBuffer();
                for (int i = 0; i < len; i++) {
                    bf.append(c2[i]);
                    bf.append(c1[i]);
                }
                ss1 = bf.substring(0, len);
                ss2 = bf.substring(len);
                if (ss1.equals(s1) && ss2.equals(s2)) {
                    flag = false;
                    break;
                }

            } while (!bf.toString().equals(s12));
            if (flag) {
                System.out.println(p + " " + step);
            } else {
                System.out.println(p + " " + -1);
            }
        }
    }
}

8. POJ 3414 Pots

原题链接:Pots
思路:容易想到BFS找出最短路,但是节点需要储存该点的前驱状态,然后利用栈先进后出将路径输出

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;


public class Main {
    static  class waterCup {
        int a,b,step,execute;//(a,b)为一个状态,step为步数,execute记录执行命令
        waterCup pre;//记录前驱节点
        waterCup(int a,int b,int step,int execute){
            this.a=a;
            this.b=b;
            this.step=step;
            this.execute=execute;
        }
    }
    static int a, b, target;
    static boolean[][]  vis=new boolean[105][105];//标记是否查找过
    static String[] cmd={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};//命令集

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        a=sc.nextInt();
        b=sc.nextInt();
        target=sc.nextInt();
        bfs();
    }

    private static void bfs() {
        Queue<waterCup> q=new ArrayDeque<waterCup>();
        waterCup fCup=new waterCup(0,0,0,0);
        fCup.pre=null;
        vis[0][0]=true;
        q.offer(fCup);
        while (!q.isEmpty()){
            waterCup nowCup=q.poll();
            //满足条件,输出
            if (nowCup.a==target||nowCup.b==target){
                print(nowCup);
                return;
            }
            //FILL(1)
            if (!vis[a][nowCup.b]){
                waterCup next0=new waterCup(a,nowCup.b,nowCup.step+1,0);
                next0.pre=nowCup;
                vis[next0.a][next0.b]=true;
                q.offer(next0);
            }
            //FILL(2)
            if (!vis[nowCup.a][b]){
                waterCup next1=new waterCup(nowCup.a,b,nowCup.step+1,1);
                next1.pre=nowCup;
                vis[next1.a][next1.b]=true;
                q.offer(next1);
            }
            //DROP(1)
            if (!vis[0][nowCup.b]){
                waterCup next2=new waterCup(0, nowCup.b,nowCup.step+1,2);
                next2.pre=nowCup;
                vis[next2.a][next2.b]=true;
                q.offer(next2);
            }
            //DROP(2)
            if (!vis[nowCup.a][0]){
                waterCup next3=new waterCup(nowCup.a,0,nowCup.step+1,3);
                next3.pre=nowCup;
                vis[next3.a][next3.b]=true;
                q.offer(next3);
            }
            int water=nowCup.a+nowCup.b;
            int na=0,nb=0;
            //POUR(1,2)
            if (nowCup.a!=0&&nowCup.b!=b) {
                if (water > b) {
                    na = water - b;
                    nb = b;
                } else {
                    na=0;
                    nb=water;
                }
                if (!vis[na][nb]){
                    waterCup next4=new waterCup(na,nb,nowCup.step+1,4);
                    next4.pre=nowCup;
                    vis[na][nb]=true;
                    q.offer(next4);
                }
            }
            //POUR(2,1)
            if (nowCup.a!=a&&nowCup.b!=0) {
                if (water > a) {
                    na = a;
                    nb = water-a;
                } else {
                    na=water;
                    nb=0;
                }
                if (!vis[na][nb]){
                    waterCup next5=new waterCup(na,nb,nowCup.step+1,5);
                    next5.pre=nowCup;
                    vis[na][nb]=true;
                    q.offer(next5);
                }
            }
        }
        //没有合法情况
        System.out.println("impossible");
    }

    private static void print(waterCup nowCup) {
        Stack<Integer> s= new Stack<Integer>();
        System.out.println(nowCup.step);//输出步数
        while (nowCup.pre!=null){//将命令路径压入栈
          s.push(nowCup.execute);
          nowCup=nowCup.pre;
        }
        while (!s.empty()){//先进后出,顺序输出命令
            int temp=s.pop();
            System.out.println(cmd[temp]);
        }

    }

}

9. FZU 2150 Fire Game

原题链接:Fire Game
思路:存所有草的数量和位置在链表里,然后遍历所有选草情况(可以两火共草)进行BFS,分别处理是否在同一位置,记录每种选法最大蔓延时间再选出其中最小值。FZU好像炸了,出了Presentation Error再交交不上去
这个结果应该是没问题

import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    static class Fire {
        int x, y, time;

        Fire(int x, int y, int time) {
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }

    static int n, m, total ;
    static int[][] map;
    static int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        for (int p = 1; p <= N; p++) {
            n = sc.nextInt();
            m = sc.nextInt();
            total=0;
            map = new int[n][m];
            LinkedList<Fire> grass = new LinkedList<Fire>();
            for (int i = 0; i < n; i++) {
                char[] cs = sc.next().toCharArray();
                for (int j = 0; j < m; j++) {
                    if (cs[j] == '#') {
                        total += 1;
                        grass.add(new Fire(i, j, 0));
                    } else {
                        map[i][j] = 1;
                    }
                }
            }
            int min = Integer.MAX_VALUE / 2;
            for (int i = 0; i < grass.size(); i++) {
                for (int j = i; j < grass.size(); j++) {
                    int time = BFS(grass.get(i), grass.get(j));
                    min = min < time ? min : time;
                }

            }

            if (min == Integer.MAX_VALUE / 2) {
                System.out.printf("Case %d: -1\n", p);
            } else {
                System.out.printf("Case %d: %d\n", p, min);
            }

        }
    }

    private static int BFS(Fire g1, Fire g2) {
        Queue<Fire> q = new ArrayDeque<Fire>();
        boolean[][] onFire = new boolean[n][m];
        int ans = 0;
        int max = 0;
        if (g1 != g2) {
            onFire[g1.x][g1.y] = true;
            onFire[g2.x][g2.y] = true;
            q.offer(g1);
            q.offer(g2);
            ans = 2;
        } else {
            onFire[g1.x][g1.y] = true;
            q.offer(g1);
            ans = 1;
        }
        while (!q.isEmpty()) {
            Fire now = q.poll();
            if (ans == total) {
                return max;
            }
            for (int i = 0; i < 4; i++) {
                int x = now.x + dir[i][0];
                int y = now.y + dir[i][1];
                if (x >= 0 && x < n && y >= 0 && y < m && !onFire[x][y] && map[x][y] == 0) {
                    onFire[x][y] = true;
                    ans += 1;
                    max = max > now.time + 1 ? max : now.time + 1;
                    q.offer(new Fire(x, y, now.time + 1));
                }
            }
        }
        return Integer.MAX_VALUE / 2;
    }
}

10. UVa 11624 Fire

原题链接:Fire
思路:多个火和一个人BFS,然后比较边界是否有人的到达时间<火的到达时间。感觉没问题但是一直超时,求大神指点

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    static int[][] map = new int[1005][1005];
    static int[][] TimeJ = new int[1005][1005];
    static int[][] TimeF = new int[1005][1005];
    static boolean[][] onFire = new boolean[1005][1005];
    static int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    static int INF = Integer.MAX_VALUE / 2, n, m;

    static class runner {
        int x, y;

        runner(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        for (int p = 0; p < N; p++) {
            n = sc.nextInt();
            m = sc.nextInt();
            int x = 0, y = 0;
            for (int i = 0; i < n; i++) {
                char[] cs = sc.next().toCharArray();
                for (int j = 0; j < m; j++) {
                    if (cs[j] == 'F') {
                        map[i][j] = 2;
                    } else if (cs[j] == 'J') {
                        map[i][j] = 1;
                        x = i;
                        y = j;
                    } else if (cs[j] == '.') {
                        map[i][j] = 1;
                    }
                }
            }

            bfs(x, y, TimeJ, 'J');
            bfs(x, y, TimeF, 'F');
            int ans = escape();
            if (ans != INF) {
                System.out.println(ans);
            } else {
                System.out.println("IMPOSSIBLE");
            }

        }
    }

    static void bfs(int x, int y, int[][] Time, char choice) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                Time[i][j] = INF;
                onFire[i][j] = false;
            }
        }
        Queue<runner> q = new ArrayDeque<runner>();
        if (choice == 'J') {
            q.offer(new runner(x, y));
            onFire[x][y] = true;
            Time[x][y] = 1;
        } else {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (map[i][j] == 2) {
                        q.offer(new runner(i, j));
                        onFire[i][j] = true;
                        Time[i][j] = 1;
                    }
                }
            }
        }
        while (!q.isEmpty()) {
            runner now = q.poll();
            for (int i = 0; i < 4; i++) {
                int nx = now.x + dir[i][0];
                int ny = now.y + dir[i][1];
                if (nx >= 0 && nx < n && ny >= 0 && ny < m && !onFire[nx][ny] && map[nx][ny] != 0) {
                    onFire[nx][ny] = true;
                    Time[nx][ny] = Time[now.x][now.y] + 1;
                    q.offer(new runner(nx, ny));
                }
            }
        }
    }

    static int escape() {
        int ans = INF;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (i == 0 || j == 0 || i == n - 1 || j == m - 1 &&TimeJ[i][j]!=INF) {
                    if (TimeJ[i][j] < TimeF[i][j]) {
                        if (TimeJ[i][j] < ans) {
                            ans = TimeJ[i][j];
                        }
                    }
                }
            }
        }
        return ans;
    }
}

11. POJ 3984 迷宫问题

原题链接:迷宫问题
思路:先从终点BFS求出最短路,再从起点DFS沿着最短路到终点,用StringBuffer储存路径

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    static class Node {
        int x, y;

        Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static int n = 5;
    static int[][] dis = new int[n][n];
    static String[][] map = new String[n][n];
    static StringBuffer bf = new StringBuffer();
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};


    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < n; i++) {
            map[i] = sc.nextLine().split("\\s++");
        }
        bfs();
        dfs();
        System.out.print(bf.toString());
    }

    private static void dfs() {
        int x = 0, y = 0;
        bf.append("(0, 0)\n");//逗号后面有空格
        while (x != n - 1 || y != n - 1) {
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (nx >= 0 && nx < n && ny >= 0 && ny < n && map[nx][ny].equals("0") ) {
                    if (dis[nx][ny] == dis[x][y] - 1) {
                        x = nx;
                        y = ny;
                        String str = "(" + x + ", " + y + ")\n";
                        bf.append(str);
                        break;
                    }
                }
            }
        }
    }
    private static void bfs() {
        Queue<Node> q = new ArrayDeque<Node>();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                dis[i][j] = -1;
            }
        }
        dis[n - 1][n - 1] = 0;
        Node node = new Node(n - 1, n - 1);
        q.offer(node);
        while (!q.isEmpty()) {
            node = q.poll();
            for (int i = 0; i < 4; i++) {
                int x = node.x + dx[i];
                int y = node.y + dy[i];
                if (x >= 0 && x < n && y >= 0 && y < n && dis[x][y] == -1 && map[x][y].equals("0")) {
                    dis[x][y] = dis[node.x][node.y] + 1;
                    q.offer(new Node(x, y));
                }
            }
        }
    }
}

12. HDU 1241 Oil Deposits

原题链接:Oil Deposits
思路:BFS,DFS都可以,思路都是寻找一个@将其标记(改为*),对他进行搜索,直到本次搜索结束,集合数+1,重新寻找下一个@做起点,当图中没有@时输出结果。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    static char[][] map;
    static int n,m;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            int sum=0;
            m=sc.nextInt();
           n=sc.nextInt();
           if (m==0&&n==0){
               return;
           }
            map=new char[m][n];
            for (int i = 0; i < m; i++) {
                map[i]=sc.next().toCharArray();
            }
            for (int i=0;i<m;i++){
                for (int j = 0; j < n; j++) {
                    if (map[i][j]=='@'){
                        dfs(i,j);
                        sum++;
                    }
                }
            }
            System.out.println(sum);
        }

    }

    private static void dfs(int i, int j) {
        map[i][j]='*';
        for (int x=-1;x<=1;x++){
            for (int y=-1;y<=1;y++){
                int a=i+x;
                int b=j+y;
                if (a>=0&&a<m&&b>=0&&b<n&&map[a][b]=='@'){
                    dfs(a,b);
                }
            }
        }
    }
}

14.HDU 2612 Find a way

原题链接:Find a way
思路:两次BFS即可

package text;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;


public class Main {
    static int[][] map, stepM, stepY;
    static int n, m;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};

    static class My {
        int x, y, time;

        My(int x, int y, int time) {
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            n = sc.nextInt();
            m = sc.nextInt();
            map = new int[n][m];
            stepM = new int[n][m];
            stepY = new int[n][m];
            int YX = 0, YY = 0, MX = 0, MY = 0;
            for (int i = 0; i < n; i++) {
                char[] cs = sc.next().toCharArray();
                for (int j = 0; j < m; j++) {
                    if (cs[j] == 'Y') {
                        YX = i;
                        YY = j;
                        map[i][j]=1;
                    } else if (cs[j] == 'M') {
                        MX = i;
                        MY = j;
                        map[i][j]=1;
                    } else if (cs[j] == '@') {
                        map[i][j] = 2;
                    } else if (cs[j] == '#') {
                        map[i][j] = 1;
                    }
                }
            }
            bfs(YX, YY, stepY);
            bfs(MX, MY, stepM);
            getResult();
        }
    }

    private static void bfs(int x, int y, int[][] step) {
        Queue<My> q = new ArrayDeque<My>();
        My me = new My(x, y, 0);
        q.offer(me);
        while (!q.isEmpty()) {
            me = q.poll();
            for (int i = 0; i < 4; i++) {
                int nx = me.x + dx[i];
                int ny = me.y + dy[i];
                if (nx >= 0 && nx < n && ny >= 0 && ny < m && step[nx][ny]==0 && map[nx][ny] != 1) {
                    step[nx][ny] = me.time + 11;
                    q.offer(new My(nx, ny, me.time + 11));
                }
            }
        }


    }

    private static void getResult() {
        int min = Integer.MAX_VALUE, sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
            //注意可能某个@是不能到达的!!!我被卡了半天
                if (map[i][j] == 2&&stepY[i][j]!=0&&stepY[i][j]!=0) {
                    sum = stepM[i][j] + stepY[i][j];
                    min = sum < min ? sum : min;
                }
            }
        }
        System.out.println(min);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值