一、打怪类
小美在玩游戏,游戏中有n个怪物,怪物的血量为hi,攻击力为ai.小美的血量为H,攻击力为A,小美可以击败血量和攻击力都小于自己的怪物,并且打败后血量降为怪物的血量,攻击力降为怪物的攻击力。小美想知道最多可以打败多少怪物。
输入描述:第一 行三个整数n, H, A,分别表示怪物的数量,小美的血量,小美的攻击力。第二行n个整数hi表示怪物的血量。第三行n个整数ai,表示怪物的攻击力。
输出描述:输出一个整数表示答案。
import java.util.Arrays;
import java.util.Scanner;
public class MonsterFight {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int H = scanner.nextInt();
int A = scanner.nextInt();
scanner.nextLine();//消耗换行符
int[] monsterHP = new int[n];
int[] monsterATK = new int[n];
for (int i = 0; i < n; i++) {
monsterHP[i] = scanner.nextInt();
}
scanner.nextLine();//消耗换行符
for (int i = 0; i < n; i++) {
monsterATK[i] = scanner.nextInt();
}
scanner.close();
// 将怪物按照血量从小到大排序
Monster[] monsters = new Monster[n];
for (int i = 0; i < n; i++) {
monsters[i] = new Monster(monsterHP[i], monsterATK[i]);
}
Arrays.sort(monsters);
int defeatedMonsters = 0;
for (int i = 0; i < n; i++) {
if (H <= 0) {
break; // 如果小美已经死亡,停止打怪
}
if (monsters[i].hp <= A) {
// 如果小美的攻击力大于等于怪物的血量,可以打败怪物
defeatedMonsters++;
H = monsters[i].hp;
A = monsters[i].atk;
}
}
System.out.println(defeatedMonsters);
}
static class Monster implements Comparable<Monster> {
int hp;
int atk;
public Monster(int hp, int atk) {
this.hp = hp;
this.atk = atk;
}
// 根据怪物的血量进行排序
@Override
public int compareTo(Monster other) {
return Integer.compare(this.hp, other.hp);
}
}
}
这道题只a出13%,我觉得这个题意是不清晰明确的,首先击败最多怪物的话应该是可以给怪物按照血值升序排序的。模糊的点在于到底怎么判断打败怪物的条件,是小美的攻击力大于怪物的血值还是如题所说小美的攻击力大于怪物的攻击力,小美的血值大于怪物的血值。
附别人的代码:
import java.util.*;
public class MonsterFight {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int H = scanner.nextInt();
int A = scanner.nextInt();
int[] h = new int[n];
int[] a = new int[n];
int[] ids = new int[n];
for (int i = 0; i < n; i++) {
h[i] = scanner.nextInt();
}
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
for (int i = 0; i < n; i++) {
ids[i] = i;
}
Arrays.sort(ids, (a1, b) -> Integer.compare(h[a1], h[b]));
int ed = -1;
for (int i = 0; i < n; i++) {
int id = ids[i];
if (h[id] >= H) {
break;
}
ed = i;
}
if (ed == -1) {
System.out.println(0);
} else {
List<Integer> nums = new ArrayList<>();
List<Integer> f = new ArrayList<>();
for (int i = 0; i <= ed; i++) {
if (a[ids[i]] >= A) {
continue;
}
nums.add(a[ids[i]]);
}
int ans = 0;
for (int i = 0; i < nums.size(); i++) {
f.add(1);
for (int j = 0; j < i; j++) {
if (nums.get(j) < nums.get(i)) {
f.set(i, Math.max(f.get(j) + 1, f.get(i)));
}
}
ans = Math.max(ans, f.get(i));
}
System.out.println(ans);
}
}
}
二、背包问题
地图上有n个城市,小美准备修建一些道路,使得任意两个城市之间都能通过道路到达。现在给定一些修路的计划 (有一些计划是必选的) ,请你帮小美规划出最优的方案。
输入描述:第一行输入两个正整数n, m用空格隔开,代表城市数量。接下来的m行,每行输入四个正整数u,v,w,p,代表一个计划是在城市u和城市v之间修建一条道路, 花费为w。如果p为1,代表该计划必选,如果p为0,代表该计划是可选的。
输出描述:如果无解(即无法使得任意两个城市之间都能通过道路到达) ,则输出-1,如果有解,则第一行输出一个正整数k,代表选择的计划数量。第二行输入k个正整数bi,代表选择的计划。你只需要保证最终所有的城市都可以通过道路连通,且总代价最小即可。请注意,p= 1的计划是必选的,如果你的方案不包含某个p= 1的计划,则会直接返回答案错误。
import java.util.*;
public class RoadConstruction {
static class Edge implements Comparable<Edge> {
int u, v, w, p;
public Edge(int u, int v, int w, int p) {
this.u = u;
this.v = v;
this.w = w;
this.p = p;
}
@Override
public int compareTo(Edge other) {
return Integer.compare(this.w, other.w);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
//消耗换行符
scanner.nextLine();
List<Edge> edges = new ArrayList<>();
List<Integer> selectedPlans = new ArrayList<>();
int totalCost = 0;
int requiredPlans = 0;
for (int i = 0; i < m; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
int w = scanner.nextInt();
int p = scanner.nextInt();
if (p == 1) {
requiredPlans++;
}
edges.add(new Edge(u, v, w, p));
}
Collections.sort(edges);
int[] parent = new int[n + 1];
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
for (Edge edge : edges) {
int u = edge.u;
int v = edge.v;
int w = edge.w;
int pu = findParent(parent, u);
int pv = findParent(parent, v);
if (pu != pv) {
parent[pv] = pu;
totalCost += w;
selectedPlans.add(edges.indexOf(edge) + 1);
}
}
if (selectedPlans.size() != n - 1 || selectedPlans.size() < requiredPlans) {
System.out.println(-1); // 无解
} else {
System.out.println(selectedPlans.size());
for (int plan : selectedPlans) {
System.out.print(plan + " ");
}
System.out.println();
}
}
static int findParent(int[] parent, int x) {
if (parent[x] != x) {
parent[x] = findParent(parent, parent[x]);
}
return parent[x];
}
}
三、按位与
小美有一个长度为n的数组,她想从中选出至少一个或多个数, 使得这些个数的按位与的结果可以被整除。例如小美有一个数组[1, 2, 4, 12],那么她可以选出[4, 12],因为4&12= 4,可以被整除,所以m的最大值为2。请帮小美选数,使得整数m尽可能的大。
输入描述:第一行一个整数n,表示数组的长度。第二行n个整数ai,表示数组的元素。
输出描述:输出一个整数,表示m的最大值。
import java.util.Scanner;
import java.util.Arrays;
public class BitwiseOperations {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
Arrays.sort(a);
int ans = get(a[n - 1]);
int rec = a[n - 1];
for (int i = n - 2; i >= 0; i--) {
rec &= a[i];
ans = Math.max(ans, get(rec));
}
System.out.println(ans);
}
static int get(int x) {
int ret = 0;
while (x != 0 && x % 2 == 0) {
x /= 2;
ret++;
}
return ret;
}
}