



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.LinkedList;
public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = (int) (1e5 + 10);static boolean[] vis = new boolean[N];static int[] res = new int[N];static info[] a = new info[N];static int n = 0, d =0, k = 0;static Dequedq = new LinkedList();public static void main(String[] args) throws Exception{String ndk[] = br.readLine().split(" ");n = Integer.parseInt(ndk[0]);d = Integer.parseInt(ndk[1]);k = Integer.parseInt(ndk[2]); for(int i = 1; i <= n; i++) {String[] ti = br.readLine().split(" ");a[i] =new info();a[i].ts = Integer.parseInt(ti[0]);a[i].id = Integer.parseInt(ti[1]);}Arrays.sort(a,1, 1 + n,new cmp());for(int i = 1; i <= n; i++) {while(!dq.isEmpty() && a[dq.getFirst()].ts + d - 1 < a[i].ts) {res[a[dq.getFirst()].id] = res[a[dq.getFirst()].id] - 1;dq.pollFirst();}while(!dq.isEmpty() && a[dq.getLast()].id != a[i].id) {res[a[dq.getFirst()].id] = res[a[dq.getFirst()].id] - 1;dq.pollFirst();}dq.addLast(i);res[a[i].id] += 1;if(res[a[i].id] >= k) {vis[a[i].id] = true;}}for(int i = 0; i < N; i++) {if(vis[i] == true) {System.out.println(i);}}}
}
class info{int ts,id;
}
class cmp implements Comparator{@Overridepublic int compare(info o1, info o2) {if(o1.id == o2.id) {return o1.ts - o2.ts;}else {return o1.id - o2.id;}}}
阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。
今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。
现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。
迷宫用一个 R×C
的字符矩阵来表示。
字符 S 表示阿尔吉侬所在的位置,字符 E 表示奶酪所在的位置,字符 # 表示墙壁,字符 . 表示可以通行。
阿尔吉侬在 1 个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static boolean[][] vis = new boolean[220][220];static char[][] map = new char[220][220];static int dx[] = {0,0,-1,1};static int dy[] = {-1,1,0,0};static Queueq = new LinkedList<>();static int r = 0, c =0, k = 0;static int sx = 0, sy = 0,ex = 0, ey = 0;static boolean ok = false;public static void main(String[] args) throws Exception{int t = Integer.parseInt(br.readLine());while(t-- > 0) {String[] rc =br.readLine().split(" ");r = Integer.parseInt(rc[0]);c = Integer.parseInt(rc[1]);init();for(int i = 1; i <= r; i++) {String a = br.readLine();for(int j = 1; j <= c; j++) {char ch = a.charAt(j - 1);if(ch =='E') {ex = i;ey = j;}if(ch == 'S') {sx = i;sy = j;}map[i][j] = a.charAt(j - 1);}}// System.out.println(ex + " " +ey);vis[sx][sy] = true;node tt = new node();tt.x = sx; tt.y = sy;tt.step = 0;q.add(tt);while(!q.isEmpty()) {int x = q.peek().x;int y = q.peek().y;if(x == ex && y == ey) {ok = true;System.out.println(q.peek().step);break;}node b = q.poll();for(int k = 0; k <= 3; k++) {int nx = b.x + dx[k];int ny = b.y + dy[k];if(nx >= 1 && nx <= r && ny >= 1 && ny <= c) {if(!vis[nx][ny] && map[nx][ny] != '#') {node temp = new node();temp.x = nx; temp.y = ny;temp.step = b.step + 1;q.add(temp);vis[nx][ny] = true;}} }}if(!ok) {System.out.println("oop!");}}}private static void init() {q.clear();ok = false;for(int i = 0; i <= r; i++) {for(int j = 0; j <= c; j++) {vis[i][j] = false;}}}
}
class node{int x,y;int step;
}
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。
你站在其中一块黑色的瓷砖上,只能向相邻(上下左右四个方向)的黑色瓷砖移动。
请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
多样例之间注意变量的重新初始化
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static boolean[][] vis = new boolean[22][22];static char[][] map = new char[22][22];static int dx[] = {0,0,-1,1};static int dy[] = {-1,1,0,0};static int w = 0, h =0, k = 0;static int sx = 0, sy = 0,ex = 0, ey = 0;static boolean ok = false;static int cnt = 0;public static void main(String[] args) throws Exception{while(true) {init();String[]wh = br.readLine().split(" ");w = Integer.parseInt(wh[0]);h = Integer.parseInt(wh[1]);if(w == 0 && h == 0) {return;}for(int i = 1; i <= h; i++) {String str = br.readLine();for(int j = 1; j <= w; j++) {char ch = str.charAt(j - 1);if(ch == '@') {sx = i;sy = j;}map[i][j] = ch;}}dfs(sx,sy);out.println(cnt);out.flush();}}private static void dfs(int x, int y) {for(int k = 0; k <= 3; k++) {int nx = x + dx[k];int ny = y + dy[k];if(nx >= 1 && nx <= h && ny >= 1 && ny <= w &&map[nx][ny] == '.' && !vis[nx][ny]) {cnt++;vis[nx][ny] = true;dfs(nx,ny);}}}private static void init() {cnt = 1;for(int i = 0; i <= 20; i++) {for(int j = 0; j <= 20; j++) {vis[i][j] = false;}}}
}


1.暴力
每个位置肯定是要回到自己的位置,我们直接从1到n进行枚举,如果当前并不是应该的数,我们就需要交换,我们从i+1开始寻找a[j]等于i,与其交换,并将操作次数++;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = 10010;static int[] fa = new int[N];static int[] a = new int[N];static int cnt = 0, n = 0;public static void main(String[] args) throws Exception{n = Integer.parseInt(br.readLine());String[]aa = br.readLine().split(" ");for(int i = 1; i <= n; i++) {a[i] = Integer.parseInt(aa[i - 1]);}for(int i = 1; i <= n; i++) {if(i != a[i]) {for(int j = i + 1; j <= n; j++) {if(a[j] == i) {int t = a[i];a[i] = a[j];a[j] = t;cnt++;}}}}System.out.println(cnt);}}
2.利用并查集(群论回环问题)💡

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = 10010;static int[] fa = new int[N];static int[] a = new int[N];static int cnt = 0, n = 0;public static void main(String[] args) throws Exception{n = Integer.parseInt(br.readLine());String[]aa = br.readLine().split(" ");init();for(int i = 1; i <= n; i++) {a[i] = Integer.parseInt(aa[i - 1]);}for(int i = 1; i <= n; i++) {merge(a[i],a[a[i]]);}for(int i = 1; i <= n; i++) {if(fa[i] == i) {cnt++;}}System.out.println(n - cnt);}private static void merge(int x, int y) {int fa_x = find(x);int fa_y = find(y);if(fa_x != fa_y) {fa[fa_y] = fa_x;}}private static int find(int x) {if(fa[x] == x) {return x;}return fa[x] = find(fa[x]);}private static void init() {for(int i = 1; i <= n; i++) {fa[i] = i;}}
}


思路:
二叉树的高度为log2n,所以开一个20的数组就够存所有深度的权值和
❗注意点:
(1)因为权值可能为负数,所以为了安全起见,我们求最大值的时候,初始化可以初始化为ds[1]
(2)求最大值的时候,同样因为存在负数,不能这季节遍历1-20,我们应该存一个最大的深度
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = 100100;static long[] ds = new long[30];static int[] a = new int[N];static int cnt = 0, n = 0;static int maxdep = 1;public static void main(String[] args) throws Exception{n = Integer.parseInt(br.readLine());String[] aa = br.readLine().split(" ");for(int i = 1; i <= n; i++) {a[i] = Integer.parseInt(aa[i - 1]);}dfs(1,1);long maxn = ds[1];int pos = 1;for(int i = 2; i <= maxdep; i++) { //注意这里不能直接遍历到20if(ds[i] > maxn) {pos = i;maxn = ds[i];}}System.out.println(pos);}private static void dfs(int p, int depth) {if(p > n) {return;}maxdep = Math.max(maxdep, depth);ds[depth] += (long)a[p]; dfs(p*2,depth + 1);dfs(p*2+1, depth + 1);}}
你现在被困在一个三维地牢中,需要找到最快脱离的出路!
地牢由若干个单位立方体组成,其中部分不含岩石障碍可以直接通过,部分包含岩石障碍无法通过。
向北,向南,向东,向西,向上或向下移动一个单元距离均需要一分钟。
你不能沿对角线移动,迷宫边界都是坚硬的岩石,你不能走出边界范围。
请问,你有可能逃脱吗?
如果可以,需要多长时间?
输入格式
输入包含多组测试数据。每组数据第一行包含三个整数 L,R,C 分别表示地牢层数,以及每一层地牢的行数和列数。
接下来是 L个 R行 C列的字符矩阵,用来表示每一层地牢的具体状况。
每个字符用来描述一个地牢单元的具体状况。
其中, 充满岩石障碍的单元格用”#”表示,不含障碍的空单元格用”.”表示,你的起始位置用”S”表示,终点用”E”表示。
每一个字符矩阵后面都会包含一个空行。
当输入一行为”0 0 0”时,表示输入终止。
输出格式
每组数据输出一个结果,每个结果占一行。
如果能够逃脱地牢,则输出”Escaped in x minute(s).”,其中X为逃脱所需最短时间。
如果不能逃脱地牢,则输出”Trapped!”。
思路:很显然就是bfs(不过是三维的,到理是一样的)
写的时候注意细节就好了
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.cert.X509CRL;
import java.util.LinkedList;
import java.util.Queue;public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = 110;static boolean[][][] vis = new boolean[N][N][N];static char[][][] map = new char[N][N][N];static int[] dx = {0,0,-1,1,0,0};static int[] dy = {-1,1,0,0,0,0};static int[] dz = {0,0,0,0,-1,1};static boolean ok = false;static int cnt = 0, n = 0,sx = 0, sy = 0,sz = 0, ex = 0, ey = 0,ez = 0;static int l = 0, r = 0, c = 0;static Queue q= new LinkedList<>();public static void main(String[] args) throws Exception{while(true) {init();String[] lrc = br.readLine().split(" ");l = Integer.parseInt(lrc[0]);r = Integer.parseInt(lrc[1]);c = Integer.parseInt(lrc[2]);if(l == 0 && r == 0 && c == 0) {return;}for(int h = 1; h <= l; h++) {for(int i = 1; i <= r; i++) {String str = br.readLine();for(int j = 1; j <= c; j++) {char ch = str.charAt(j - 1);if(ch == 'S') {sx = i;sy = j;sz = h;}if(ch == 'E') {ex = i;ey = j;ez = h;
// System.out.println(ex + " " + ey + " " + ez);}map[h][i][j] = ch;}}br.readLine();}node t = new node(sz,sx,sy,0);vis[sz][sx][sy] = true;q.add(t);while(!q.isEmpty()) {node tt = q.poll();if(tt.z == ez && tt.x == ex && tt.y == ey) {ok = true;cnt = tt.step;break;}for(int k = 0; k <= 5; k++) {int nx = tt.x + dx[k];int ny = tt.y + dy[k];int nz = tt.z + dz[k];if(check(nz,nx,ny)) {vis[nz][nx][ny] = true;node temp = new node(nz, nx, ny, tt.step + 1);q.add(temp);}}}if(ok) {System.out.printf("Escaped in %d minute(s).\n",cnt);}else {System.out.println("Trapped!");}}}private static boolean check(int nz, int nx, int ny) {if(nz >= 1 && nz <= l && nx >= 1 && nx <= r && ny >= 1 && ny <= c && !vis[nz][nx][ny] && map[nz][nx][ny] != '#') {return true;}return false;}private static void init() {q.clear();ok = false;for(int h = 1; h <= l; h++) {for(int i = 1; i <= r; i++) {for(int j = 1; j <= c; j++) {vis[h][i][j] = false;map[h][i][j] = ' ';}}}}}class node{int x,y,z;int step;public node(int z,int x,int y,int step) {this.z = z;this.x = x;this.y = y;this.step = step;}
}


思路:
首先dfs(Flood Fill)判断起初有多少独立的岛屿(连通块),我们需要把每一块进行标号,(因为淹没完以后如果一个岛屿的两部分不相连了,但是让算作一个岛屿,所以我们需要进行编号)然后模拟淹没,最后遍历统计有多少不同的编号即可(使用集合去重即可)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.cert.X509CRL;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;public class Main{static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int N = 1100;static boolean[][] vis = new boolean[N][N];static int[][] id = new int[N][N];static char[][] map = new char[N][N];static char[][] cmap = new char[N][N];static int[] dx = {0,0,-1,1};static int[] dy = {-1,1,0,0};static boolean ok = false;static Setst = new HashSet<>();static int cnt1 = 0, cnt2= 0,n = 0,sx = 0, sy = 0,sz = 0, ex = 0, ey = 0,ez = 0;static int l = 0, r = 0, c = 0;public static void main(String[] args) throws Exception{n = Integer.parseInt(br.readLine());for(int i = 1; i <= n; i++) {String str = br.readLine();for(int j = 1; j <= n; j++) {char ch = str.charAt(j - 1);map[i][j] = ch;cmap[i][j] = ch;}}for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(map[i][j] == '#' && !vis[i][j]) {vis[i][j] = true;cnt1++;id[i][j] = cnt1;dfs(i,j);}}}flood();for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(cmap[i][j] == '#') {st.add(id[i][j]);}}}System.out.println(cnt1 - st.size());}private static void flood() {for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(map[i][j] == '#') {for(int k = 0; k <= 3; k++) {int nx = i + dx[k];int ny = j + dy[k];if(check1(nx, ny)) {if(map[nx][ny] == '.') {cmap[i][j] = '.';}}}}}}}private static void dfs(int x, int y) {for(int k = 0; k <= 3; k++) {int nx = x + dx[k];int ny = y + dy[k];if(check(nx, ny)) {vis[nx][ny] = true;id[nx][ny] = cnt1;dfs(nx,ny);}}}private static boolean check(int nx, int ny) {if(nx >= 1 && nx <= n && ny >= 1 && ny <= n && !vis[nx][ny] && map[nx][ny] == '#') {return true;}return false;}private static boolean check1(int nx, int ny) {if(nx >= 1 && nx <= n && ny >= 1 && ny <= n) {return true;}return false;}
}

