赞
踩
模拟题,塔子哥提交ac
package ZhenTi; import java.sql.SQLOutput; import java.util.Scanner; /** * 5/6喷墨水 */ public class Solution29 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); sc.nextLine(); String[] strs = sc.nextLine().split(" "); int[] arr = new int[n]; for(int i=0,c=0; i<strs.length && c<n; i++){ //十六进制变十进制变二进制,前两位0x为前缀 char[] bs = Integer.toBinaryString(Integer.parseUnsignedInt(strs[i].substring(2),16)) .toCharArray(); //长度不足16,后边的用0填充 for(int j=0;j<16-bs.length&&c<n;j++){ arr[c++] = 0; } for(int j=0;j<bs.length&&c<n;j++){ arr[c++] = bs[j]- '0'; } } // System.out.println(arr); int ans,ans1=-1,ans2=-1; //检查向右移动,从0开始遍历,只求最短的,找到了就返回 for(int i=0;i<n;i++){ if(check(arr,i,0)){ ans1 = i; break; } } //检查向左移动 for(int i=0;i<n;i++){ if(check(arr,i,1)){ ans2 = i; break; } } ans = (ans1==-1?0:1) + (ans2==-1?0:1); System.out.println(ans); if(ans1!=-1){ System.out.println("+" + ans1); int[] res = new int[n]; for(int i=0;i<n;i++){ if(arr[i]==0){ //输出要求堵塞的孔开启即可,因此先找到堵塞的孔处理 if(arr[i]==0){ res[i-ans1] = 1; } } } for(int item:res){ System.out.print(item); } System.out.println(); } if(ans2!=-1){ System.out.println("-" + ans2); int[] res = new int[n]; for(int i=0;i<n;i++){ if(arr[i]==0){ //输出要求堵塞的孔开启即可,因此先找到堵塞的孔处理 if(arr[i]==0){ res[i+ans2] = 1; } } } for(int item:res){ System.out.print(item); } } } //cnt表示位移步数,dir表示移动方向,0表示向右移动,1表示向左移动 public static boolean check(int[] arr,int cnt,int dir){ int ans = 0; int n = arr.length; if(dir==0){//向右移动 for(int i=0,j;i<n;i++){ //两种情况:不移动可以实现喷墨或者向右移动cnt位也能实现喷墨 if(arr[i]==1 || ((j=i-cnt)>=0&&arr[j]==1 )){ ans++; }else{ break; } } }else{//向左移动 for(int i=0,j;i<n;i++){ //两种情况:不移动可以实现喷墨或者向左移动cnt位也能实现喷墨 if(arr[i]==1 || ((j=i+cnt)<n&&arr[j]==1 )){ ans++; }else{ break; } } } return ans == n;//如果ans等于数组长度n就说明喷墨成功 } }
复杂的模拟题,塔子哥提交AC
分成数字和特殊字符两部分,转换成数字相加,就不需要考虑进位的问题了
首先,遇到特殊字符就将该位换成0,并记录下特殊字符和位置,最后得到数字部分的值相加。 然后计算特殊字符相加的值,也就是题目中表达式的值乘上10的(所在位置相对小数点的位置)幂次方,比如小数点后一位就乘上10的-1幂次方。 最后转字符串处理并输出。
package ZhenTi; /** * 5/6 模拟加法 华为 */ import java.math.BigDecimal; import java.util.*; public class Solution30{ static HashMap<String,Double> sp = new HashMap<>();//特殊字符的加法原则 static StringBuilder spl = new StringBuilder();//记录所有的特殊字符 static BigDecimal cnt = BigDecimal.valueOf(0.0);//记录处理特殊字符后的数字 static int count = 0; public static void main(String[] args) { Scanner in = new Scanner(System.in); in.nextLine(); String[] str = in.nextLine().split("\\+"); String left = str[0]; //第一个数 String right = str[1]; //第二个数 HashMap<Integer,Integer> leftSpecial = divide(left);//个数(从0开始):索引 HashMap<Integer,Integer> rightSpecial = divide(right);//得到cnt 用0替代特殊字符后,两个数字之和 //加法规则 sp.put("!+!",0.0); sp.put("!+@",13.0);sp.put("@+!",13.0); sp.put("!+#",4.0);sp.put("#+!",4.0); sp.put("@+@",7.0); sp.put("@+#",20.0);sp.put("#+@",20.0); sp.put("#+#",5.0); //处理特殊字符 int l = spl.length() / 2;//第一个数字的特殊字符的位置和第二数字对应特殊字符位置相差len/2 int index = 0; for (int i = 0; i < l; i++) { String temp = spl.charAt(i) + "+" + spl.charAt(l + i); int idx = left.indexOf('.');//判断是否有小数点 if(idx == -1){//没有小数点, 最终结果为 sum*10^index index = left.length() - leftSpecial.get(i) - 1; }else{//有小数点,如果特殊字符在整数部分sum*10^index;小数部分,sum*10^-index int tem = leftSpecial.get(i); if(tem < idx){ index = idx - tem - 1; }else{ index = -(tem - idx); } } Double num = sp.get(temp) * Math.pow(10,index); String tempnum = String.valueOf(num); BigDecimal bigtemp = new BigDecimal(tempnum); cnt = cnt.add(bigtemp);//特殊字符的求和结果 } //处理结果:去除后置0和小数点 StringBuilder res = new StringBuilder(cnt.toString()); int length = res.length(); while(res.charAt(length -1) == '0'){ res.deleteCharAt(length - 1); length--; } if(res.charAt(length - 1) == '.'){ res.deleteCharAt(length - 1); } System.out.println(res); } //处理数字:把特殊字符变为0 public static HashMap<Integer,Integer> divide(String str){ int l = str.length(); //存在小数点,返回索引;否则返回-1 int index = str.indexOf("."); //保存特殊字符索引 HashMap<Integer,Integer> Special = new HashMap<>();//count特殊字符个数-1 : i在字母中对应索引 StringBuilder res = new StringBuilder(); if(index == -1){ //无小数点 for (int i = 0; i < l; i++) { //特殊字符用0替代 if(str.charAt(i) < '0' || str.charAt(i) > '9'){ Special.put(count,i);//放入哈希表 count++;//特殊字符统计个数+1 spl.append(str.charAt(i));//记录特殊字符 res.append('0');//用0代替 }else{//普通字符直接添加 res.append(str.charAt(i)); } } }else{ //有小数点,以小数点为间隔做相同的处理 中间加上小数点即可 for (int i = 0; i < index; i++) { if(str.charAt(i) < '0' || str.charAt(i) > '9'){ //特殊字符; Special.put(count,i); count++; spl.append(str.charAt(i)); res.append('0'); }else{ res.append(str.charAt(i)); } } res.append('.'); for (int i = index + 1; i < l; i++) { //有小数点 if(str.charAt(i) < '0' || str.charAt(i) > '9'){ //特殊字符; Special.put(count,i); count++; spl.append(str.charAt(i)); res.append('0'); }else{ res.append(str.charAt(i)); } } } BigDecimal bigres = new BigDecimal(res.toString()); cnt = cnt.add(bigres);//记录处理特殊字符后的数字,相加,得到数字1和数字2的和 return Special; } }
最短路模型
队列元素:x坐标,y坐标,时间轮次
每一个轮次 遍历四个方向 + 停留在原地
package ZhenTi; import java.util.ArrayDeque; import java.util.Queue; import java.util.Scanner; /** * 5/6华为第三题:找公主 */ public class Solution31 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); //大小,怪物数量 int n = scan.nextInt(), k = scan.nextInt(); boolean[][] traps = new boolean[n][n];//怪物位置 for (int i = 0; i < k; i++) { traps[scan.nextInt()][scan.nextInt()] = true; } //公主和王子的位置 int gx = scan.nextInt(), gy = scan.nextInt(), wx = scan.nextInt(), wy = scan.nextInt(); String[][] strings = new String[n][]; scan.nextLine(); for (int i = 0; i < n; i++) { strings[i] = scan.nextLine().split(" "); } char[][][] grid = new char[n][n][3];//地图表格 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { grid[i][j] = strings[i][j].toCharArray(); } } boolean[][][] vis = new boolean[n][n][3]; int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; Queue<int[]> queue = new ArrayDeque<>(); queue.offer(new int[]{wx, wy, 0});//两个坐标+时间轮次 int ans = 0; while (!queue.isEmpty()) { for (int i = queue.size(); i > 0; i--) { int[] cur = queue.poll(); if (cur[0] == gx && cur[1] == gy) {//找到了公主 System.out.println(ans); return; } int turn = (cur[2] + 1) % 3;//计算当前轮次 for (int[] dir : dirs) {//四个方向搜索 int x = cur[0] + dir[0], y = cur[1] + dir[1]; //边界,是否有怪物,障碍,是否访问过 if (x < 0 || x >= n || y < 0 || y >= n || traps[x][y] || grid[x][y][turn] == '1' || vis[x][y][turn]) continue; queue.offer(new int[]{x, y, turn}); vis[x][y][turn] = true; } //可以选择停留在原地,当下一个轮次没有障碍物且未访问过 if (grid[cur[0]][cur[1]][turn] != '1' && !vis[cur[0]][cur[1]][turn]) { queue.offer(new int[]{cur[0], cur[1], turn}); vis[cur[0]][cur[1]][turn] = true; } } ans++;//步长 } System.out.println(-1); } }
package ZhenTi; /** * 网络最小可达跳数之和 * 多源最短路径BFS * 参考leetcodeT417. 太平洋大西洋水流问题 */ import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class Solution6 { static int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}}; static boolean[][] visited; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); String[][] str = new String[n][n]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ str[i][j] = sc.next(); } } visited = new boolean[n][n]; //开始处理:从目标点反向搜索 Queue<int[]> que = new LinkedList<>(); int[][] nums = new int[n][n];//每个点到达终点的步数,BC默认0 int res = 0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if (str[i][j].equals("C")){ que.offer(new int[]{i,j}); } } } while(!que.isEmpty()){ int[] temp = new int[2]; temp[0] = que.peek()[0]; temp[1] = que.poll()[1]; for(int[] dir:dirs){ int newX = temp[0] + dir[0]; int newY = temp[1] + dir[1]; if(newX<0||newY<0||newX>=n||newY>=n||visited[newX][newY]|| !str[newX][newY].equals("A")){//边界条件+访问过+非A continue; } que.offer(new int[]{newX,newY}); visited[newX][newY] = true; nums[newX][newY] = nums[temp[0]][temp[1]]+1; res += nums[newX][newY]; } } System.out.println(res); } }
构建连接图,dfs找到每个点的前继点的个数
自定义排序,技巧性可以学习
初始化大小不能设置太大,根据题目数据大小设置,一开始多打了个0,一直超时
import java.util.*; public class Main { static Map<Integer, List<Integer>> map = new HashMap<>();//节点:依赖该节点的 public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); //处理逻辑 //构建每个点的依赖关系 //初始化 数据最多100000 for(int i=0;i<100010;i++){ map.put(i,new ArrayList<>()); } for(int i=0;i<n;i++){ int temp = sc.nextInt(); if(temp!=-1){ map.get(temp).add(i);//节点:依赖该节点的 } } //DFS找到每个节点的依赖点的个数 List<int[]> res = new ArrayList<>();// [a,b]a表示依赖点的个数,b表示节点序号 for(int i=0;i<n;i++){ res.add(new int[]{dfs(i),i}); } //自定义排序 Collections.sort(res, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { if(o1[0]!=o2[0]){ return o2[0]-o1[0]; }else{ return Integer.compare(o1[1], o2[1]); } } }); for(int[] item:res){ System.out.print(item[1]+" "); } } public static int dfs(int i){ int count = 0; for(int j:map.get(i)){ count += dfs(j); } return count+1; } }
理论学习:
参考文章
package ZhenTi; /** * https://blog.codefun2000.com/company/mt/3-18/P1087.html#%E4%BB%A3%E7%A0%81 */ import java.util.Scanner; public class Solution33 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int a = sc.nextInt(); int b = sc.nextInt(); int[][] mp = new int[1011][1011]; for(int i = 0; i < n; i++) { int x = sc.nextInt(); int y = sc.nextInt(); mp[x][y]++; } // 求二维前缀和 //map[i][j] 表示左上角以(0,0),右下角(i,j)的矩形里有多少个敌人 for(int i = 1; i <= 1010; i++) { for(int j = 1; j <= 1010; j++) { //二维前缀和公式推导见资料,右上角被重复算了,需要减 mp[i][j] += mp[i-1][j] + mp[i][j-1] - mp[i-1][j-1]; } } // 枚举技能矩阵的右下角,并求矩形伤害总和的最大值 int ans = 0; for(int i = a+1; i <= 1010; i++) { for(int j = b+1; j <= 1010; j++) { int t = mp[i][j] - mp[i-a-1][j] - mp[i][j-b-1] + mp[i-a-1][j-b-1]; ans = Math.max(ans, t); } } System.out.println(ans); } }
leetcode239改版,求两次滑窗,
package ZhenTi; import java.util.Deque; import java.util.LinkedList; import java.util.Scanner; public class Solution34 { public static void main(String[] args) { //为了方便处理下输入 Scanner sc = new Scanner(System.in); String s = sc.nextLine(); String[] sub1 = s.substring(s.indexOf('[')+1,s.indexOf(']')).split(","); int[] nums = new int[sub1.length]; for(int i=0;i<nums.length;i++){ nums[i] = Integer.parseInt(sub1[i]); } String[] sub2 = s.substring((s.indexOf('k'))).split("="); int k = Integer.parseInt(sub2[sub2.length-1]); //开始处理 int size = nums.length - k + 1; int[] resMax = new int[size]; int[] resMin = new int[size]; resMax = slidingWindow(nums,k,true); resMin = slidingWindow(nums,k,false); int res = Integer.MIN_VALUE; for(int i=0;i<size;i++){ res = Math.max(res,resMax[i]-resMin[i]); } System.out.println(res); } public static int[] slidingWindow(int[] nums, int k,boolean flag) { if(nums.length == 1) return nums; int[] res = new int[nums.length-k+1];//所有滑窗里的最大值 MyDeque que = new MyDeque(); for(int i=0;i<k;i++){ que.add(nums[i],flag); } res[0] = que.peekMax(); int index = 1; for(int i=k;i<nums.length;i++){ que.removeFirst(nums[i-k]);//删除滑窗第一个元素(可能不存在) que.add(nums[i],flag); res[index++] = que.peekMax(); } return res; } } class MyDeque{ Deque<Integer> deque = new LinkedList<>(); //增 //flag为true 单调递减队列 //flag为false 单调递减增队列 public void add(int val,boolean flag){ if(flag){ while(!deque.isEmpty() && val>deque.getLast()){ deque.removeLast(); } deque.add(val); }else{ while(!deque.isEmpty() && val<deque.getLast()){ deque.removeLast(); } deque.add(val); } } //删:删除滑窗的第一个元素,只有相等才需要删除 public void removeFirst(int val){ if(!deque.isEmpty()&&val == deque.peek()){ deque.pollFirst(); } } //返回最大值 public int peekMax(){ return deque.peek(); } }
import java.util.*; public class Main{ static List<Integer>[] edges; static int[] counts; static int[] eC; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); edges = new List[N+1]; for (int i = 0; i < edges.length; i++) { edges[i] = new ArrayList<>(); } for (int i = 1; i < N; i++) { int to = sc.nextInt(); int from = sc.nextInt(); edges[to].add(from); edges[from].add(to); } eC = new int[N+1]; counts = new int[N+1]; dfs(1,-1); dfs1(1,-1,N); int ans = Integer.MAX_VALUE; int ansCount = 0; for (int i = 2; i <= N ; i++) { if (ans == eC[i]){ ansCount++; }else if (ans>eC[i]){ ans = eC[i]; ansCount = 1; } } System.out.println(ans+" "+ansCount); } private static void dfs1(int root, int father,int N) { List<Integer> edge = edges[root]; for (Integer integer : edge) { if (integer!=father){ eC[integer] = Math.abs(N-counts[integer]-counts[integer]); dfs1(integer,root,N); } } } private static void dfs(int root, int father) { List<Integer> edge = edges[root]; int ans = 1; for (Integer integer : edge) { if (integer!=father){ dfs(integer,root); ans+=counts[integer]; } } counts[root] = ans; } }
过了样例 网站没过 可以参考下注释
package ZhenTi; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Scanner; /** * https://codefun2000.com/p/P1177 * 拆分树-dfs 美团 */ public class Solution35 { static List<List<Integer>> edges = new ArrayList<>();//记录相连的边 static int[] count;//记录每个节点对应的节点个数 static int[] tempResult;//删除边后(该节点到父节点的边)的两棵树的节点差值 public static void main(String[] args) { Scanner sc = new Scanner(System.in); //初始化 int n = sc.nextInt(); for(int i=0;i<=n;i++){ edges.add(new ArrayList<>()); } for(int i=1;i<n;i++){ int child = sc.nextInt(); int parent = sc.nextInt(); edges.get(child).add(parent); edges.get(parent).add(child); } count = new int[n+1]; tempResult = new int[n+1]; //遍历每个节点对应的节点数:更新count //默认父节点为1 dfs1(1,-1); //删除每条边后的答案:更新tempResult,不用dfs也可以 dfs2(1,-1,n); int res = Integer.MAX_VALUE; int resCount = 0; for(int i=2;i<=n;i++){ if(res==tempResult[i]){ resCount++; }else if(res>tempResult[i]){ res = tempResult[i]; resCount=1; } } System.out.println(res+" "+resCount); } public static void dfs1(int child,int parent){ List<Integer> tempEdge = edges.get(child); int res = 1;//节点数为1 for(Integer temp:tempEdge){//遍历每个子节点 if(temp!=parent){ dfs1(temp,child); res += count[temp];//所有子节点的累加 } } count[child] = res; } public static void dfs2(int child,int parent,int n){ List<Integer> edge = edges.get(child); for(Integer temp:edge){ if(temp!=parent){ tempResult[temp] = Math.abs(n-count[temp]-count[temp]); dfs2(temp,child,n); } } } }
分两种情况,遇到R就变成W,W不用变化;处理逻辑:拿到点,往下搜索满足条件就插入合并为同一组
import java.util.Scanner; public class Main{ static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上下左右四个方向 static int[] father; // 并查集数组 static int numRedBlocks; // 红色连通块个数 public static void main(String[] args) { //初始化 Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int m = scanner.nextInt(); scanner.nextLine(); // 读取换行符 char[][] matrix = new char[n][m]; for (int i = 0; i < n; i++) { matrix[i] = scanner.nextLine().replaceAll(" ", "").toCharArray(); } // int[][] res = new int[n][m]; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if (matrix[i][j] == 'R') { matrix[i][j] = 'W'; res[i][j] = countRedBlock(matrix,n,m); matrix[i][j] = 'R'; }else{ res[i][j] = countRedBlock(matrix,n,m); } } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ System.out.print(res[i][j]+" "); } System.out.println(); } } public static int countRedBlock(char[][] matrix,int n,int m) { father = new int[n * m];//并查集 numRedBlocks = 0; //计算红色区域数量 for (int i = 0; i < n * m; i++) { father[i] = i; if (matrix[i / m][i % m] == 'R') { numRedBlocks++; } } //合并红色格子 for (int i = 0; i < n * m; i++) { int row = i / m; int col = i % m; if (matrix[row][col] == 'R') { for (int[] dir : dirs) { int nRow = row + dir[0]; int nCol = col + dir[1]; //遇到R:就往下走 if (nRow >= 0 && nCol >= 0 && nRow < n && nCol < m && matrix[nRow][nCol] == 'R') { union(i,nRow*m+nCol);//若两个父节点不一致就合并且减去红色区域数量 } } } } return numRedBlocks; } //找父节点 public static int findRoot(int x){ if (x != father[x]) { father[x] = findRoot(father[x]); } return father[x]; } //合并:x插入y public static void union(int x,int y){ int rootX = findRoot(x); int rootY = findRoot(y); if(rootX!=rootY){ father[rootX] = rootY; numRedBlocks--; } } }
最小对最小,最大对最大;a排序后,b用一个二维数组记录索引,排序后再根据索引求a
package ZhenTi; import java.util.Arrays; import java.util.Scanner; /** * https://codefun2000.com/p/P1100 */ public class Solution37 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] a = new int[n]; int[][] b = new int[n][2]; for(int i=0;i<n;i++){ a[i] = sc.nextInt(); } for(int i=0;i<n;i++){ b[i][0] = sc.nextInt(); b[i][1] = i; } Arrays.sort(a); Arrays.sort(b,(x,y)->{ return x[0]-y[0]; });//数组b按数字大小排序 //把a的值赋值到b for(int i=0;i<n;i++){ b[i][0] = a[i]; } //对更新后的b按索引排序 Arrays.sort(b,(x,y)->{ return x[1]-y[1]; }); for(int i=0;i<n;i++){ System.out.print(b[i][0]+" "); } } }
往两边dfs
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main{ static List<List<Integer>> edges = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for(int i=0;i<n;i++){ edges.add(new ArrayList<>()); } for(int i=2;i<=n;i++){ int num = sc.nextInt(); edges.get(num-1).add(i-1); edges.get(i-1).add(num-1); } int x = sc.nextInt()-1; int y = sc.nextInt()-1; System.out.println(dfs(x,y)+dfs(y,x)+1);//需要加1 本身 } public static int dfs(int start,int end){ int res = 0; for(int num:edges.get(start)){ if(num!=end){ res = Math.max(res,dfs(num,start)+1); } } return res; } }
添加链接描述
正常DFS一次,染色后DFS一次,求连通区域
package ZhenTi; import java.util.Arrays; import java.util.Scanner; /** * https://codefun2000.com/p/P1094 * 岛屿数量进阶版 */ public class Solution39 { static char[][] colors; static boolean[][] visited; static int[][] dirs = {{-1,0},{1,0},{0,1},{0,-1}}; static int m; static int n; public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); sc.nextLine(); colors = new char[m][n]; visited = new boolean[m][n]; for(int i=0;i<m;i++){ colors[i] = sc.nextLine().toCharArray(); } //整除情况 int count1=0; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(!visited[i][j]){ dfs(i,j); count1++; } } } int count2 = 0; //染色 for(int i=0;i<m;i++){ Arrays.fill(visited[i],false); } for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(colors[i][j]=='G'){ colors[i][j] = 'B'; } } } for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(!visited[i][j]){ dfs(i,j); count2++; } } } System.out.println(count1-count2); } public static void dfs(int x,int y){ visited[x][y] = true; for(int[] dir:dirs){ int nx = x + dir[0]; int ny = y + dir[1]; if(nx>=0&&ny>=0&&nx<m&&ny<n&&colors[x][y]==colors[nx][ny]&&!visited[nx][ny]){ dfs(nx,ny); } } } }
package ZhenTi; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; /** * https://codefun2000.com/p/P1275 * 华为 开心消消乐 */ public class Solution40 { static int m; static int n; static int[][] nums; static int[][] dirs = {{-1,0},{1,0},{0,1},{0,-1},{1,-1},{1,1},{-1,1},{-1,-1}}; public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); nums = new int[m][n]; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ nums[i][j] = sc.nextInt(); } } int res = 0; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(nums[i][j]==1){ bfs(i,j);//遇到1就开始染色 res++; } } } System.out.println(res); } public static void bfs(int x,int y){ Queue<int[]> que = new LinkedList<>(); que.offer(new int[]{x,y}); while(!que.isEmpty()){ int[] temp = que.poll(); for(int[] dir:dirs){ int nx = temp[0] + dir[0]; int ny = temp[1] + dir[1]; if(nx>=0&&nx<m&&ny>=0&&ny<n&&nums[nx][ny]==1){ nums[nx][ny] = 0;//更新染色点 que.offer(new int[]{nx,ny}); } } } } }
BFS Queue(X,Y,速度) + 状态记录
输出不好处理
package ZhenTi; /** * https://codefun2000.com/p/P1295 * 华为 BFS 加一个维度 */ import java.util.*; public class Solution41 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String[] s = sc.nextLine().trim().split(","); int n = Integer.parseInt(s[0]), m = Integer.parseInt(s[1]); s = sc.nextLine().trim().split(","); int sx = Integer.parseInt(s[0]), sy = Integer.parseInt(s[1]); int[][] h = new int[n][m], o = new int[n][m]; s = sc.nextLine().trim().replace(" ", ",").split(","); for (int i = 0, idx = 0; i < n; i++) { for (int j = 0; j < m; j++) { h[i][j] = Integer.parseInt(s[idx++]); } } s = sc.nextLine().trim().replace(" ", ",").split(","); for (int i = 0, idx = 0; i < n; i++) { for (int j = 0; j < m; j++) { o[i][j] = Integer.parseInt(s[idx++]); } }//输入 // 状态记录 Map<Integer, Set<Integer>> map = new HashMap<>(); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { map.put(i * m + j, new HashSet<>());//对于每一个点开辟一个set记录出现过的速度 } } Queue<int[]> q = new LinkedList<>();//开辟队列 map.get(sx * m + sy).add(1); q.offer(new int[]{sx, sy, 1});//初始点入队列 int cnt = 0; int[][] dirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; while (!q.isEmpty()) { int[] t = q.poll(); int x = t[0], y = t[1], v = t[2]; for (int[] dir : dirs) { int a = x + dir[0], b = y + dir[1]; if (a < 0 || a >= n || b < 0 || b >= m) continue;//上面几句BFS经典操作 int nv = v + h[x][y] - h[a][b] - o[a][b];//求得速度 if (nv <= 0 || map.get(a * m + b).contains(nv)) continue;//一旦发现(x,y,v)已经被记录或者v<=0时就跳过 if (nv == 1) cnt++;//如果(x,y,1)第一次发生,答案就加1 map.get(a * m + b).add(nv);//更新map,存储每一个(x,y,v) q.offer(new int[]{a, b, nv});//BFS经典操作 } } System.out.println(cnt); } }
import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int size = sc.nextInt(); List<Integer>[] edges = new List[size+1]; for(int i=1;i<=size;i++){ edges[i] = new ArrayList<>(); } for(int i=2;i<=size;i++){ int n = sc.nextInt(); edges[i].add(n); edges[n].add(i); } char[] colors = new char[size+1]; sc.nextLine(); String str = sc.nextLine(); for(int i=0;i<size;i++){ colors[i+1] = str.charAt(i); } //处理 //dp[i][3] 第i个节点为根节点,对应的三种颜色的数量 //dfs1记录每个点 //dfs2找到切割方案的次数 int[][] dp = new int[size+1][3]; boolean[] visited = new boolean[size+1]; dfs1(edges,colors,visited,dp,1); Arrays.fill(visited,false); System.out.println(dfs2(edges,colors,visited,dp,1)); } public static void dfs1(List<Integer>[] edges,char[] colors,boolean[] visited,int[][] dp,int index){ //更新访问状态,遍历三种颜色 visited[index] = true; if(colors[index]=='R'){ dp[index][0]++; } if(colors[index]=='G'){ dp[index][1]++; } if(colors[index]=='B'){ dp[index][2]++; } //遍历所连接的每一条边 for(int temp:edges[index]){ if(visited[temp]){continue;} dfs1(edges,colors,visited,dp,temp);//更新子节点 for(int i=0;i<3;i++){ dp[index][i] += dp[temp][i];//父节点等于子节点之和 } } } public static int dfs2(List<Integer>[] edges,char[] colors,boolean[] visited,int[][] dp,int index){ int res = 0; visited[index] = true; if(index!=1&&check(dp[index],dp[1])){ res++; } for(int next:edges[index]){ if(visited[next]) {continue;} res += dfs2(edges,colors,visited,dp,next); } return res; } //判断左子树或者右子树是否满足条件 public static boolean check(int[] cur,int[] root){ for(int i=0;i<3;i++){ if(cur[i]==0||root[i]-cur[i]==0){ return false; } } return true; } }
import java.util.Arrays; import java.util.Scanner; /** * https://codefun2000.com/p/P1082 * 阿里 树形dp (记忆化搜索) */ class TreeNode{ int val; TreeNode left; TreeNode right; public TreeNode(int val){ this.val = val; } } public class Main { static int[] dp;//-2表示未搜索过 -1表示不是满二叉树 n表示节点个数 public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); dp = new int[n+1]; Arrays.fill(dp,-2);//要先初始化为-2 TreeNode[] nodes = new TreeNode[n+1]; for(int i=1;i<n+1;i++){ nodes[i] = new TreeNode(i); } for(int i=1;i<=n;i++){ int left = sc.nextInt(); int right = sc.nextInt(); if(left!=-1) nodes[i].left = nodes[left]; if(right!=-1) nodes[i].right = nodes[right]; } int res = 0; for(int i=1;i<=n;i++){ if(dfs(nodes[i])>=0){res++;} } System.out.println(res); } //以节点node开始搜索,三种情况:1.已经搜索过;2. public static int dfs(TreeNode node){ if(node == null) return 0; if(dp[node.val]!=-2) return dp[node.val];//记忆化搜索 int left = dfs(node.left); int right = dfs(node.right); if(left==-1||right==-1||left!=right){ dp[node.val] = -1;//不是满二叉树 }else{ dp[node.val] = left+1; } return dp[node.val]; } }
import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); while(n>0){ int m = sc.nextInt(); int[] nums = new int[m]; int[] res = new int[m]; for(int i=0;i<m;i++){ nums[i] = sc.nextInt(); } //前到后遍历 int[][] prev = new int[m][2]; if(nums[0]==1){ prev[0][1] = 1; }else{ prev[0][0] = 0; } for(int i=1;i<m;i++){ if(nums[i]==0){ prev[i][0] = prev[i-1][0] + 1; prev[i][1] = prev[i-1][1]; }else{ prev[i][1] = prev[i-1][1] + 1; prev[i][0] = prev[i-1][0]; } } int[] right = new int[2]; right[0] = prev[m-1][0]; right[1] = prev[m-1][1]; //后到前遍历 int[][] next = new int[m][2]; if(nums[m-1]==1){ next[m-1][1] = 1; }else{ next[m-1][0] = 0; } for(int i=m-2;i>=0;i--){ if(nums[i]==0){ next[i][0] = next[i+1][0] + 1; next[i][1] = next[i+1][1]; }else{ next[i][1] = next[i+1][1] + 1; next[i][0] = next[i+1][0]; } } int[] left = new int[2]; left[0] = next[0][0]; left[1] = next[0][1]; // for(int i=0;i<m;i++){ if(nums[i]==0){ res[i] = right[0]-prev[i][0]+left[1]-next[i][1]; }else{ res[i] = right[1]-prev[i][1]+left[0]-next[i][0]; } System.out.print(res[i]+" "); } System.out.println(""); n--; } } }
import java.util.*; public class Main{ static List<List<Integer>> child = new ArrayList<>(); static List<Integer> colors = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for(int i=0;i<n;i++){ child.add(new ArrayList<>()); } for(int i= 1;i<n;i++){ child.get(sc.nextInt()-1).add(i); } for(int i=0;i<n;i++){ colors.add(sc.nextInt()); } System.out.println(dfs(0)); } public static int dfs(int n){ if(child.get(n).isEmpty()){//空节点返回1 return 1; } int sum = 0; //1个节点和2个节点 A^0=A A+0=0 for(int next:child.get(n)){ if(colors.get(n)==1){ sum += dfs(next);//红色累加 }else{ sum ^= dfs(next);//绿色异或 } } return sum; } }
import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); while(n-->0){ int m = sc.nextInt(); int[][] nums = new int[m][2]; //[数字,索引] for(int j=0;j<m;j++){ nums[j][0] = sc.nextInt(); nums[j][1] = j; } //按照数字大小排序 Arrays.sort(nums,(a,b)->(a[0]-b[0])); int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; int res = 0; //索引范围包含数字即是排列 for(int k=0;k<m;k++){ max = Math.max(max,nums[k][1]); min = Math.min(min,nums[k][1]); if(max-min<=k){ res++; } } System.out.println(res); } } }
import java.util.*; public class Main{ static int size; static List<List<Integer>> joinList; static int[] value; static int[] res; public static void main(String[] args) { Scanner sc = new Scanner(System.in); size = sc.nextInt(); joinList = new ArrayList<>(); value = new int[size]; res = new int[size]; for(int i=0;i<size;i++){ value[i] = sc.nextInt(); } for(int i=0;i<size;i++){ joinList.add(new ArrayList<>()); } for(int i=0;i<size-1;i++){ int from = sc.nextInt()-1; int to = sc.nextInt()-1; joinList.get(from).add(to); } dfs(0); for(int i=0;i<size;i++){ System.out.print(res[i]+" "); } } public static int[] dfs(int index){ int[] split = splitTwoFive(value[index]); //计算每个数分解成2和5的个数 int[] tempRes = new int[2]; for(int next:joinList.get(index)){ tempRes = dfs(next);//取子节点的值,更新 split[0] += tempRes[0]; split[1] += tempRes[1]; } res[index] = Math.min(split[0],split[1]);//结果由最小值决定 return split; } public static int[] splitTwoFive(int node){ int count2 = 0; int count5 = 0; while(node != 0){ if(node%2==0){ count2++; node = node/2; }else{ break; } } while(node != 0){ if(node%5==0){ count5++; node = node/5; }else{ break; } } return new int[]{count2,count5}; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。