思路分析,一共有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);
}
}