7.12刷题总结

 思路分析,一共有N个地窖,每一个地窖有一定数量的地雷,从一共地方开始挖地雷,只能选择一条路径开始挖,当没有连接时挖地雷工作结束,设计一个方案,使某人能挖到最多的地雷。

可以使用深度优先搜索,类似于回溯的操作,

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

public class 扫地雷dfs版本 {
    static int[][] graph; //存储地窖的邻接矩阵
    static int[] mines; //地雷数量
    static int maxCount; //地雷的总数
    static List<Integer> maxPath; //最大路径

    public static void dfs(int current, List<Integer> path, int count) {
        path.add(current); //将当前加入到路径中
        count += mines[current]; //总数++;

        if (count > maxCount) {
            //求出来最大,更新最大值
            maxCount = count;
            maxPath = new ArrayList<>(path);
        }

        //变量当前地雷相邻的地雷
        for (int neighbor = 0; neighbor < graph[current].length; neighbor++) {
            //如果相邻的地窖与当前地窖相通,且相邻的地窖不再当前的路径上面,继续搜索
            if (graph[current][neighbor] == 1 && !path.contains(neighbor)) {
                dfs(neighbor, path, count);
            }
        }
       // 撤销 回溯操作
        path.remove(path.size() - 1);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();

        mines = new int[n];
        for (int i = 0; i < n; i++) {
            mines[i] = scanner.nextInt();
        }

        graph = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                graph[i][i + j + 1] = scanner.nextInt();//将图转为二维灵界矩阵
            }
        }

        maxCount = 0;
        maxPath = new ArrayList<>();

        for (int start = 0; start < n; start++) {
            //每一个节点都会进行搜索
            dfs(start, new ArrayList<>(), 0);
        }

        for (int node : maxPath) {
            //加1 匹配的是索引
            System.out.print((node + 1) + " "); // Adding 1 to convert from 0-based indexing to 1-based indexing
        }
        System.out.println();
        System.out.println(maxCount);
    }
}

leetcode 2751 栈+模拟

现有 n 个机器人,编号从 1 开始,每个机器人包含在路线上的位置、健康度和移动方向。

给你下标从 0 开始的两个整数数组 positions、healths 和一个字符串 directions(directions[i] 为 'L' 表示 向左 或 'R' 表示 向右)。 positions 中的所有整数 互不相同 。

所有机器人以 相同速度 同时 沿给定方向在路线上移动。如果两个机器人移动到相同位置,则会发生 碰撞 。

如果两个机器人发生碰撞,则将 健康度较低 的机器人从路线中 移除 ,并且另一个机器人的健康度 减少 1 。幸存下来的机器人将会继续沿着与之前 相同 的方向前进。如果两个机器人的健康度相同,则将二者都从路线中移除。

请你确定全部碰撞后幸存下的所有机器人的 健康度 ,并按照原来机器人编号的顺序排列。即机器人 1 (如果幸存)的最终健康度,机器人 2 (如果幸存)的最终健康度等。 如果不存在幸存的机器人,则返回空数组。

在不再发生任何碰撞后,请你以数组形式,返回所有剩余机器人的健康度(按机器人输入中的编号顺序)。

注意:位置 positions 可能是乱序的。

示例 1:

机器人发生碰撞,健康比较低的直接小时,健康高的-1,如果两个机器人健康值相等,那么两个都消失

考虑 如何去模拟这个过程

每一个机器人都有一个下标对应的索引,根据对应的position进行排序,用lamada表达式快速进行排序,把id排序一下,就是机器人对应的位置

用栈来模拟的思路,找到向右走的机器人,添加到战中来,如果机器人是向左走到,那么根据题目的规则,进行比较,如果一样向右的出栈,且两个healths都为0;

如果不等的话,看哪一个比较大,左边大,就左边减减,右边healths=0;同理。

最后在变量所有的健康指数,如果大于0,就将其添加到集合中去。找到剩余健康的机器人。

引入id数组,为了让directions和healths通过id联系起来,id需要进行排序,根据positions的顺序。


import java.util.Arrays;
import java.util.Stack;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public List<Integer> survivedRobotsHealths(int[] positions, int[] healths, String directions) {
        //给每一个机器人一个下标索引位置
        int n=positions.length;
      Integer [] id= new Integer[n];
      //为下面的排序埋下了伏笔
        for (int i = 0; i <n; i++) {
            id[i]=i;
        }
        //根据机器人的位置进行排序
        Arrays.sort(id,(i,j)-> positions[i]-positions[j]);
        //创建一个栈,用于存储向右的机器人索引
        Stack<Integer> stack =new Stack<>();
        //用position来替换了id的值;
        for (int i:id){
            //对id进行了排序
            if(directions.charAt(i)=='R'){
                //机器人向右运动的
                stack.push(i);
                continue;
            }
            while(!stack.isEmpty()){
                int top=stack.peek(); //临时搞出来的

                if (healths[top]>healths[i]){
                    //栈顶机器人的健康值大,
                    healths[top]--;
                    healths[i]=0;
                    break;
                }
                if (healths[top] == healths[i]) { // 如果栈顶的机器人健康值和当前机器人的健康值相等,将栈顶和当前机器人的健康值设为0,并退出循环
                    healths[stack.pop()] = 0;
                    healths[i] = 0;
                    break;
                }
                healths[stack.pop()] = 0; // 否则,栈顶的机器人的健康值设为0,当前机器人的健康值减一
                healths[i]--;
            }
        }

        List<Integer> ans = new ArrayList<>();
        for (int h : healths) {
            if (h > 0) {
                ans.add(h);
            }
        }
        return ans;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

走迷宫问题

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;

public class 迷宫2{
	static int num;
	static int xsize = 4;//x坐标
	static int ysize = 6;//y坐标
	static char[][] arr = new char[xsize][ysize]; //存放迷宫的字符数组
	static boolean[][] help = new boolean[xsize][ysize];//辅助数组,用于标记已经访问的位置

	static int[][] dir = {{1,0},{0,-1},{0,1},{-1,0}};//方向标记
	static char[] sign = {'D','L','R','U'};//方向标记


	//static int[][] dir = {{0,-1},{-1,0},{1,0},{0,1}};
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

		for(int i=0;i<xsize;i++){

			arr[i] = in.readLine().toCharArray();
		}
		out.println(bfs());
		out.print(num);
		out.flush();
	}
	
	static String bfs() {
		Queue<Node> list = new LinkedList<>();//存储节点
		int x = 0;
		int y = 0;
		int runnum = 0;//当前步数
		list.add(new Node(x,y,"",runnum));
		while(!list.isEmpty()){
			Node now = list.poll();
			help[now.x][now.y] = true;
			for(int i=0;i<4;i++){
				int xx = now.x + dir[i][0];
				int yy = now.y + dir[i][1];
				if(check(xx,yy) && help[xx][yy]==false && arr[xx][yy]=='0'){
					list.add(new Node(xx,yy,now.num + sign[i],now.runnum + 1));
					 //到了最后一个位置了
					if(xx==xsize-1 && yy==ysize-1){
						num = now.runnum + 1;
						return now.num + sign[i];
					}
				}
			}
		}
		return "";
	}

	private static boolean check(int xx, int yy) {
		// TODO Auto-generated method stub
		return xx>=0 && yy>=0 && xx<xsize && yy<ysize;
	}
	
	static class Node{
		int x;
		int y;
		int runnum; //走的步数
		String num;//走的字符
		public Node(int x, int y,String num ,int runnum) {
			super();
			this.x = x;
			this.y = y;
			this.num = num;
			this.runnum = runnum;
		}
	}
}

全球变暖

.表示海洋 #表示陆地  上下左右四个方向连在一起的陆地组成一座岛屿,下图存在两个岛屿,海平面上升,如果陆地有一块和海洋相邻就会被淹没,上下左右相邻。 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class 回暖 {
    //思路就是 用两个数组,一个是淹没前的,一个是淹没后的, 第一次求出所有的岛屿

    //写一个求岛屿的代码。  再写一个淹没的代码,淹没前的岛屿数量减去淹没后的岛屿数量

    // 大概的框架就是这个

    //
    // 首先先
    public static void main(String[] args) throws IOException{
        // TODO Auto-generated method stub
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(in.readLine());
        char[][] x = new char[n][n];
        char[][] s = new char[n][n];
        for(int i=0;i<n;i++){
            String a = in.readLine();
            x[i] = a.toCharArray();
            s[i] = a.toCharArray();
        }
        //求淹没前的岛屿数量
        int res1 = num(x,n);
     //淹没岛屿
        f(s,n);
        
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                System.out.print(s[i][j]);
            }
            System.out.println();
        }
        //淹没后的岛屿数量
        int res2 = num(s,n);
        out.println(res1-res2);
        out.flush();
    }

    private static int num(char[][] s,int n) {
        int sum = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                //如果遇到了 #,就就是陆地,岛屿数量+1;
                //然后进入dfs;
                if(s[i][j]=='#'){
                    sum++;
                    dfs(s,i,j,n);
                }
            }
        }
        return sum;
    }

    private static void f(char[][] s,int n) {
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(s[i][j]=='#'){
                    if(i==0 && s[i+1][j]=='.'){
                        //判断是第一行,下一行为逗号;
                        s[i][j]=',';
                    }else if(i==n-1 && s[i-1][j]=='.'){
                        //最底下那个点
                        s[i][j]=',';
                    }else if(j==0 && s[i][j+1]=='.'){
                        s[i][j]=',';
                    }else if(j==n-1 && s[i][j-1]=='.'){
                        s[i][j]=',';
                    }else if(s[i+1][j]=='.' || s[i][j+1]=='.' || s[i-1][j]=='.' || s[i][j-1]=='.'){
                        //周围有一个点是海洋了,
                        s[i][j]=',';
                    }
                }
            }
        }
    }

    private static void dfs(char[][] s,int i,int j,int n) {
        if(i<0 || j<0 || i>=n || j>=n) {
            return;
        }

        if(s[i][j]=='.')
            return; //如果是海洋直接返回

        s[i][j]='.'; //必须是陆地,才能继续往下走,将陆地淹没吊

        dfs(s,i+1,j,n);
        dfs(s,i-1,j,n);
        dfs(s,i,j+1,n);
        dfs(s,i,j-1,n);
    }
}

蓝桥杯 

分考场

题目描述
�
n 个人参加某项特殊考试。

为了公平,要求任何两个认识的人不能分在同一个考场。

求最少需要分几个考场才能满足条件。

输入描述
输入格式:

第一行,一个整数 
�
n (
1
≤
�
≤
100
1≤n≤100),表示参加考试的人数。

第二行,一个整数 
�
m,表示接下来有 
�
m 行数据。

以下 
�
m 行每行的格式为:两个整数 
�
,
�
a,b,用空格分开 ( 
1
≤
�
,
�
≤
�
1≤a,b≤n )表示第 
�
a 个人与第 
�
b 个人认识。

输出描述
输出一行一个整数,表示最少分几个考场。

输入输出样例
示例
输入

5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
copy
输出

4
copy
运行限制
最大运行时间:1s
最大运行内存: 256M
import java.util.Scanner;

public class 分考场 {

    static int n, min = 100;
    static int arr[][];
    static int examRoom[][];
    static int examStuNum[];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int m = sc.nextInt();
        arr = new int[n + 1][n + 1]; //学生之间的关系
        examRoom = new int[n + 1][n + 1]; //考场里面的关系
        examStuNum = new int[n + 1];//每个考场当前的人数,下标代表考场,对应的值代表人数
        int a, b;
        for (int i = 1; i <= m; i++) {
            a = sc.nextInt();
            b = sc.nextInt();
            arr[a][b] = 1;
            arr[b][a] = 1;
        }
        dfs(1, 0);
        System.out.println(min);
    }
    static void dfs(int stuNum, int examNum) {
        if (examNum >= min) return;
        if (stuNum > n) {
            min = examNum < min ? examNum : min;
            return;
        }
        for (int i = 1; i <= examNum; i++) {
            int j;
            for (j = 1; j <= examStuNum[i]; j++) {
                //examStrNum 第几个考场
                if(arr[stuNum][examRoom[i][j]]==1){
                    //这个人  是不是和i号考场这个人之间是不是认识的
                    break;
                }
            }
            if(j==examStuNum[i]+1){
             //说明和这个考场里面所有的人都不认识
                examRoom[i][++examStuNum[i]]=stuNum; //将这个人加进来   继续下一次的变量。

                dfs(stuNum+1,examNum);

                //回溯 不把你放到这来
                --examStuNum[i];
            }
        }
           //说明这个考场有认识的人
        //那么在加一个考场 examRoom +1;
        //考场学生的数量,第几个考场学生的数量
        // examNum+1 加一个考场  examStuNum[examNum+1]这个考场里面的人数++;
        examRoom[examNum+1][++examStuNum[examNum+1]]=stuNum;

        dfs(stuNum+1,examNum+1);

        --examStuNum[examNum+1];
    }

}

 直接tmd暴力搜索

public class 有奖问答 {
    static  int sum=0;
    public static void main(String[] args) {

        //活动一共三十道题目,每一道题只有对和错
    dfs(1,0);
        System.out.println(sum);
    }

    public  static  void  dfs (int step,int score){

        if (score==70){
            sum++;
           //return;
        }
       if (score==100){
           return;
       }
       if (step==31){
           return;
       }
        dfs(step+1,0);
        dfs(step+1,score+10);
    }
}

public class 有奖问答 {
    static  int sum=0;
    public static void main(String[] args) {

        //活动一共三十道题目,每一道题只有对和错
    dfs(1,0);
        System.out.println(sum);
    }

    public  static  void  dfs (int step,int score){

        if (score==70){
            sum++;
           //return;
        }
       if (score==100){
           return;
       }
       if (step==31){
           return;
       }
        dfs(step+1,0);
        dfs(step+1,score+10);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈阿星

您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值