一、牛的学术圈Ⅰ(二分)


如果不考虑参数L的影响,那就是一个纯纯的二分答案,问题在于如何处理参数L?,仔细读题,题目说了总共至多引用L篇,每篇论文至多引用1次,至多的意思是说可以引用也可以不引用。 那我们就先不考虑L的影响,遍历所有论文,只要论文的引用次数比二分答案(指数),大或等于或者比答案小1都可以算满足,然后统计出来看总的>=h指数的论文篇数是否达到了h篇(>=),是不是很简单?这个时候再考虑L的影响,L无非是对论文引用+1的次数有限制,那我们只要在统计论文篇数时取L和之前和答案差1的论文篇数的较小值即可。

import java.util.*;public class Main {static int[] cnt;static int N, L;public static void main(String[] args) {Scanner scan = new Scanner(System.in);N = scan.nextInt();L = scan.nextInt();// N 论文篇数// L 能够自己引用的论文数(可以提高某个论文的引用数)至多每篇论文引用一次cnt = new int[N];for (int i = 0; i < N; i++) cnt[i] = scan.nextInt();int left = 0;// 最大h指数只能为N + 1(因为每个论文至多再+1)int right = N + 1;int mid = 0;int ans = 0;while (left <= right) {mid = left + (right - left) / 2;if (check(mid)) {// 当前指数可以,那就往大的找ans = mid;left = mid + 1;} else {right = mid - 1;}}System.out.println(ans);}static boolean check(int mid) {int tmp = 0;// 下面记录需要添加引用才能够的论文int tmpp = 0;for (int i = 0; i < N; i++) {if (cnt[i] >= mid) tmp++;else if (mid - cnt[i] == 1) tmpp++; }// 最多引用L次tmpp = Math.min(tmpp, L);tmp += tmpp;// 当前满足mid指数的文章数>=mid指数就可以if (tmp >= mid) return true;return false;}
}

二、打包(二分)


二分答案即可,关键是二分里面的check内容不太好理解:

import java.util.*;public class Main {static int n, m;static int[] gift;public static void main(String[] args) {Scanner scan = new Scanner(System.in);n = scan.nextInt();m = scan.nextInt();gift = new int[n];int left = 0;int right = 0;for (int i = 0; i < n; i++) {gift[i] = scan.nextInt();left = Math.max(left, gift[i]);right += gift[i];}// 二分区间:[max(gift), sum(gift)]int mid = 0;int ans = 0;while (left <= right) {mid = left + (right - left) / 2;if (check(mid)) {ans = mid;// 最大重量最小,往小的缩小right = mid - 1;} else {left = mid + 1;}}System.out.println(ans);}  static boolean check(int mid) {// 当前最大重量是否满足m个包裹的需求?int curPackage = 0;  // 当前包裹数int curWeight = 0;  // 当前包裹总量for (int i = 0; i < n; i++) {// 注意要连续打包curWeight += gift[i];if (curWeight > mid) {// 大于最大重量的要求,重新打一个包裹curPackage++;curWeight = gift[i];}}// 注意,只要包裹数大于题目要求包裹数就肯定falseif (curPackage + 1 > m) return false;// 但如果包裹书小于等于题目要求就说明当前mid所代表的最大重量太大了,还可以缩减return true;}
}

记需要包的数量为sum。如果sum<=m,也就是说最大重量Target拿完所有礼物绰绰有余,例如本来需要4个包才能装下的现在只需要两个,Target的值可能太大了,那么答案ans<=Target;如果sum>m,说明最大重量Target下装不完所有礼物,那只能够增大Target的值,答案ans>Target,枚举直到二分查找结束。

※三、闯关(动态规划、最大子序列和问题)


这道题非常有意思,它限制了必须从第一关开始,最后一关结束,然后想要到达最后一关时,取得的金钱数最大,并且限制了每次能够到达的位置关系,抛开其它所有限制条件,回到问题本身,这就是一道:求数组最大子序列和的问题(子序列指保证数组顺序的相对关系,可以删除数组中某一个、几个元素,也可以不删除,但不能改变数组的顺序)

dp[i]表示以第 i 关结束的最多能够获取的金币数,我们可以初始化所有的dp[i] = 第一关能够获取到的金币数量,因为第一关必须打,然后对于后面每一关,我们遍历可以从前面跳转到该位置的关卡(可以从第一关、第二关…当然要满足题目对m的限制),直到遍历到最后一关,我们需要的答案就是dp[n]。

import java.util.*;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();int m = scan.nextInt();int p = scan.nextInt();long[] v = new long[n + 1];for (int i = 1; i <= n; i++) {v[i] = scan.nextLong();// 提前计算好每一关能够赚的金币数v[i] -= p;}// 必须从第1关打起long[] dp =new long[n + 1];// 每个位置必须从第1关开始Arrays.fill(dp, v[1]);// dp[i]: 以第i关结尾的最多金钱数for (int i = 2; i <= n; i++) {// 必须从第一关开始打起,所以第一关就不用考虑int begin = Math.max(1, i - m);// 遍历前面能够到达关卡i的关卡jlong max = Long.MIN_VALUE;for (int j = begin; j <= i - 1; j++) {max = Math.max(max, dp[j] + v[i]);}dp[i] = max;}System.out.println(dp[n]);}
}

这道题真的很巧妙,用的模板就是很老套、很熟悉的模板,但是如果不细细品味,很难发掘这道题的思路。

※四、怪物森林(二分答案+BFS)


题目要求是找到所有路径中,每条路径中的最小值的最大值,就是先找每条路径的最小值,然后保证这个最小值在所有路径中最大。尝试过很多方法,包括优先队列啥的,发现没用,后面看了大佬的方法,太牛了!二分答案,然后再用BFS去判断,看当前的攻击力是否能够达到终点即可。

这道题用C++可以跑过,但是Java由于本身System.out.println读入读出很慢,所以后面几个点超时了,思路是正确的。

import java.util.*;class node {int x, y;node(){}node (int x, int y) {this.x = x;this.y = y;}
}
public class Main {static int[] x = new int[] {0,0,1,-1};static int[] y = new int[] {1,-1,0,0};static int[][] monster;static boolean[][] vis;static Queue<node> queue;static int n, m;public static void main(String[] args) {Scanner scan = new Scanner(System.in);n = scan.nextInt();m = scan.nextInt();monster = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {monster[i][j] = scan.nextInt();}}int left = -1000000000;int right = monster[0][0];int mid = 0;int ans = 0;// 二分答案while (left <= right) {mid = left + (right - left) / 2;if (check(mid)) {ans = mid;left = mid + 1;} else {right = mid - 1;}}System.out.println(ans);}static boolean check(int mid) {// BFS广搜queue = new LinkedList<>();vis = new boolean[n][m];queue.offer(new node(0, 0));vis[0][0] = true;while (!queue.isEmpty()) {node tmp = queue.poll();for (int i = 0; i < 4; i++) {int tx = tmp.x + x[i];int ty = tmp.y + y[i];if (tx < 0 || ty < 0 || tx >= n || ty >= m || vis[tx][ty]) continue;// 二分的是答案,也就是路径上最小的攻击力,不能有攻击力比mid还小,否则肯定不能走这里if (monster[tx][ty] < mid) continue;vis[tx][ty] = true;queue.offer(new node(tx, ty));}}// 判断当前攻击力是否能够访问到终点return vis[n - 1][m - 1];}
}

※五、智能体系列赛(DFS搜搜)


刚开始想的是最小生成树,发现不对劲啊,这东西要求必须从起点开始,最小生成树只是说连通所有节点就行,很明显不对,发现问题后赶紧转变思路,因为每个点都能到任意点,所以每次dfs搜索需要遍历所有点,当然要用vis数组标记。

import java.beans.Visibility;
import java.util.*;public class Main {static int[] x = new int[] {0,0,1,-1};static int[] y = new int[] {1,-1,0,0};static int ans = Integer.MAX_VALUE;static int n;static boolean[] vis;static int[][] mine;public static void main(String[] args) {Scanner scan = new Scanner(System.in);int xi = scan.nextInt();int yi = scan.nextInt();n = scan.nextInt();  // 矿点数// 读取每个矿点坐标,把边存一下mine = new int[n][2];vis = new boolean[n];for (int i = 0; i < n; i++) {mine[i][0] = scan.nextInt();mine[i][1] = scan.nextInt();}// 注意呀vis数组中压根没存开始位置,所以开始位置只会被遍历1次dfs(xi, yi, 0, 0);System.out.println(ans);}static void dfs(int x, int y, int cnt, int step) {if (step > ans) return;if (cnt == n) {// 所有位置遍历完了ans = Math.min(ans, step);return;}// 遍历可能去到的点的位置for (int i = 0; i < n; i++) {if (vis[i]) continue;step += Math.abs(x - mine[i][0]) + Math.abs(y - mine[i][1]);cnt++;  // 去过的地方++vis[i] = true;dfs(mine[i][0], mine[i][1], cnt, step);// 回溯vis[i] = false;cnt--;step -= Math.abs(x - mine[i][0]) + Math.abs(y - mine[i][1]);}}
}

※六、秘密行动(动态规划)


在每一层它可以向上跳1、2层(直接是跳1、2层楼),也可以靠花费1个单位时间走1高度(每个楼层有各自的高度),现在说:跳了之后,必须靠走,才能继续跳,问到达顶层需要至少多少时间?

考虑当前层 i,它可以由上一层跳、或者走上来,所以这就有两种状态,一个是楼层数,一个是路径方法,所以是个二维DP。

import java.util.*;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();int[] hei = new int[n + 1];for (int i = 1; i <= n; i++) hei[i] = scan.nextInt();int[][] dp = new int[n + 1][2];dp[1][0] = 0;  // 第一层楼靠跳dp[1][1] = hei[1];  // 第一层楼靠走for (int i = 2; i <= n; i++) {// 到达这一层靠走,那可以跳完走,也可以走了继续走,反正只可能从上一层转换过来dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][1]) + hei[i];  // 走的话必须要把这一层楼走完// 到达这一层靠跳,那前面必须是走,跳的话可以跳1、2层dp[i][0] = Math.min(dp[i - 1][1], dp[i - 2][1]);}System.out.println(Math.min(dp[n][1], dp[n][0]));}
}

七、搬运冰块(贪心)


注意本题,冰块在搬运过程中是不融化的!看样例输入,我们按照冰块ti / di的比值,从小到大排序即可。

import java.util.*;class ice {int t, d;ice(){}ice(int t, int d) {this.t = t;this.d = d;}
}
public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();ice[] ices = new ice[n];for (int i = 0; i < n; i++) {int tt = scan.nextInt();int dd = scan.nextInt();ices[i] = new ice(tt, dd);}Arrays.sort(ices, new Comparator<ice>() {@Overridepublic int compare(ice o1, ice o2) {int t1 = o1.t;int d1 = o1.d;int t2 = o2.t;int d2 = o2.d;// t/d 两个分数比较大小t1 *= d2;t2 *= d1;int tmp = d1;d1 *= d2;d2 *= tmp;return t1 - t2;}});long cnt = 0;for (int i = 0; i < n; i++) {int t = ices[i].t;for (int j = i + 1; j < n; j++) {cnt += (long)(t * ices[j].d);}}System.out.println(cnt);}
}

八、Cat And Mouse(模拟搜索)


让猫和老鼠一起动,遇到障碍物就按题目意思进行转向,这里必须要猫鼠一起动,单靠猫、鼠一个人动,是不能找到递归出口的!导致一直递归下去,StackOverflow。

import java.util.*;public class Main {static char[][] map;public static void main(String[] args) {/***...*.....
......*...
...*...*..
..........
...*.C....
*.....*...
...*......
..M......*
...*.*....
.*.*......*/Scanner scan = new Scanner(System.in);map = new char[10][10];// 记录到达每个点的时间// 读入地图,并记录猫、老鼠的起点int cati = 0, catj = 0;int mousei = 0, mousej = 0;for (int i = 0; i < 10; i++) {map[i] = scan.nextLine().toCharArray();for (int j = 0; j < 10; j++) {if (map[i][j] == 'C') {cati = i;catj = j;}if (map[i][j] == 'M') {mousei = i;mousej = j;}}}// 分两次遍历猫、老鼠行进路线即可
//      平时沿直线走,下一步如果会走到障碍物上去或者出界,就用1秒的时间做一个右转90°。一开始它们都面向北方。dfs(cati, catj, mousei, mousej, 0, 0, 0);}// 猫的坐标、老鼠的坐标static void dfs(int i, int j, int k, int t, int dirC, int dirM, int time) {if (i == k && j == t) {// 相遇了System.out.println(time);return;}int ti = i, tj = j, tk = k, tt = t;if (dirC == 0) {if (i - 1 < 0 || map[i - 1][j] == '*') {// 转向不移动dirC = 3;} else {// 可以走ti -= 1;}} else if (dirC == 1) {// 左走if (j - 1 < 0 || map[i][j - 1] == '*') {// 转向不移动dirC = 0;} else {// 可以走tj -= 1;}} else if (dirC == 2) {// 下走if (i + 1 >= 10 || map[i + 1][j] == '*') {// 转向不移动dirC = 1;} else {// 可以走ti += 1;}} else {// 右走if (j + 1 >= 10 || map[i][j + 1] == '*') {// 转向不移动dirC = 2;} else {// 可以走tj += 1;}}// 老鼠的位置  i j k tif (dirM == 0) {if (k - 1 < 0 || map[k - 1][t] == '*') {// 转向不移动dirM = 3;} else {// 可以走tk -= 1;}} else if (dirM == 1) {// 左走if (t - 1 < 0 || map[k][t - 1] == '*') {// 转向不移动dirM = 0;} else {// 可以走tt -= 1;}} else if (dirM == 2) {// 下走if (k + 1 >= 10 || map[k + 1][t] == '*') {// 转向不移动dirM = 1;} else {// 可以走tk += 1;}} else {// 右走if (t + 1 >= 10 || map[k][t + 1] == '*') {// 转向不移动dirM = 2;} else {// 可以走tt += 1;}}dfs(ti, tj, tk, tt, dirC, dirM, time + 1);}
}

九、答疑(贪心)



按照题目意思,因为后面的同学会一直等待前面在问问题的同学,也就是说前面的同学问问题的时间越久,后面同学等的越久,累计总和越大,所以,我们可以按照三个同学的三个时间累加和,从小到大排序,这样就可以保证后面同学的等待时间较短。

import java.util.*;class stu {int s, a, e;stu(){}stu(int s, int a, int e) {this.s = s;this.a = a;this.e = e;}
}
public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();stu[] S = new stu[n];for (int i = 0; i < n; i++) {S[i] = new stu();S[i].s = scan.nextInt();S[i].a = scan.nextInt();S[i].e = scan.nextInt();}// 按照时间总和从小到大排序,因为后面发消息的时刻一定会累加前面发消息的时刻,包括其它的等待时间// 所以让总和从小到大排序,保证每个人的发消息时间都小Arrays.sort(S, new Comparator<stu>() {@Overridepublic int compare(stu o1, stu o2) {return (o1.s + o1.a + o1.e) - (o2.s + o2.a + o2.e);}});// 计算发消息的时刻总和long ans = 0;long curTime = 0;for (int i = 0; i < n; i++) {curTime = curTime + S[i].a + S[i].s;ans += curTime;curTime += S[i].e;}System.out.println(ans);}
}

十、矩阵翻转


这道题试了DFS,但是超时了,还没看懂网上大佬咋做的…

【算法练习】杂题混讲一:Acwing + 蓝桥杯练习相关推荐

  1. 20190509杂题选讲

    这次杂题选讲好多思维题神仙题啊= =顺便学了波线段树上二分= = Normal 题目大意戳这 CF1083C CDW讲的神仙题*1 题解戳这 AGC002E 我讲的题,是个人写的程序都比我写的程序跑得 ...

  2. ACWING蓝桥杯每日一题python

    ACWing蓝桥杯每日一题 一直没时间去总结算法,终于有空可以总结一下刷的acwing了,因为没时间所以最近只刷了ACWING的蓝桥杯每日一题...真是该死 1.截断数组 首先我们要知道,如果sum( ...

  3. 算法刷题系列(四)蓝桥杯python算法训练3(下)

    上一次的节点选择算法由于春节过年耽搁了,现在重新补上 上篇链接:算法刷题系列(四)蓝桥杯python算法训练3 - 经验教训 在纷繁复杂的使用了列表来暂存数据之后,发现其实可以利用笔者自己不太常用的字 ...

  4. AcWing 蓝桥杯AB组辅导课 01、递归与递推

    文章目录 前言 一.递归 知识点 例题 题目1:AcWing 95.斐波那契数列[简单,递归写法] 题目2:AcWing 92.递归实现指数型枚举[简单] 题目3:AcWing 94.递归实现排列型枚 ...

  5. AcWing蓝桥杯AB组辅导课10、疑难杂题

    文章目录 前言 例题1:AcWing 1242. 修改数组(并查集) 分析 题解:单链表式并查集 例题2:AcWing 1234. 倍数问题(背包问题+贪心) 分析 题解1:01背包问题,三维解法(贪 ...

  6. AcWing蓝桥杯AB组辅导课08、数论

    文章目录 前言 一.数论 例题 例题1:AcWing 1246. 等差数列(最大公约数,第十届蓝桥杯省赛C++B第7题) 分析 题解:最大公约数 例题2:AcWing 1295. X的因子链(算数基本 ...

  7. AcWing蓝桥杯AB组辅导课07、贪心

    文章目录 前言 一.贪心 模板题 例题1:AcWing 104. 货仓选址(贪心,简单,算法竞赛进阶指南) 分析 题解:贪心思路 例题 例题1:AcWing 1055. 股票买卖 II(贪心.状态机, ...

  8. AcWing 蓝桥杯AB组辅导课 05、树状数组与线段树

    文章目录 前言 一.树状数组 1.1.树状数组知识点 1.2.树状数组代码模板 模板题:AcWing 1264. 动态求连续区间和 例题 例题1.AcWing 1265. 数星星[中等,信息学奥赛一本 ...

  9. [JZOJ]杂题选讲

    目录 1.aplusb 2.可见点数 3.射击 4.创世纪 5.长方形 6.连通块 7.Ede的新背包问题 8.模板串 9.Clock Sequence 10.硬币游戏 1.aplusb Descri ...

最新文章

  1. UML中的六种关系的比较与学习
  2. 我收集的网上公开的免费电子书
  3. 基于基站定位数据的商圈分析代码详细解释
  4. 如何在Windows上使用64位Web浏览器
  5. JAVA world转图片,将Kinect深度图像转换为真实世界坐标
  6. 积分竞猜网php源码_贵州省网络安全知识竞赛个人赛Writeup
  7. 26. Magento 常用(1)
  8. vector 实现二维数组
  9. 诺,你们要的Python进阶来咯!【函数、类进阶必备】
  10. mina框架详解-小白收藏
  11. selenium tips
  12. 利用计算机网络实现OA的功能,中小企业oa办公系统解决方案怎么做?
  13. matlab解韩信点兵问题,小学数学题目巧解—韩信点兵问题
  14. GC调优基础知识之工具篇--jdk为我们提供的命令行命令 jps,jstat,jmap,jinfo,jstat,jstack,jhat 等
  15. TCP/IP五层模型之数据链路层
  16. 智能语音:好玩的语音控制是怎么实现的?学习笔记01
  17. android模拟按键方法,Android随笔之——模拟按键操作的几种方式
  18. Python财务分析
  19. 分布式任务调度平台XXL-JOB深度实战
  20. 【嵌入式系统开发15】STM32F103C8T6下通过定时器Timer方式实现时间的精准控制,实现串口通信并让LED等周期性地闪烁

热门文章

  1. NTP时间服务器配置以及错误的总结
  2. 网站服务器如何导入数据库,网站服务器如何导入数据库
  3. 网络安全工作需要具备的10种能力
  4. rem 布局动态 js封装动态获取屏幕宽度
  5. 超详解“二分法查找”,一看就会!
  6. Java学习之JavaSE-Java语言基础
  7. php xcopy,xcopy命令部分用法总结
  8. SQL基础知识——WHERE
  9. Dubbo的RoundRobin负载均衡
  10. ManagementClass类——ManagementClass 构造函数