第一题: 最大报酬
使用动态规划解题
import java.util.Scanner;
public class nF {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
int n = scanner.nextInt();
int[] t = new int[n];
int[] w = new int[n];
for (int i = 0; i < n; i++) {
t[i] = scanner.nextInt();
w[i] = scanner.nextInt();
}
int[][] dp = new int[n + 1][T + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= T; j++) {
if (t[i - 1] <= j) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - t[i - 1]] + w[i - 1]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
System.out.println(dp[n][T]);
}
}
第二题: 最大利润
import java.util.Scanner;
public class nD {
// 3
// 3
// 4 5 6
// 1 2 3
// 4 3 2
// 1 5 3
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int item = scan.nextInt();
int days = scan.nextInt();
int[] maxNum = new int[item];
int[][] arr = new int[item][days];
for (int i = 0; i < item; i++) {
maxNum[i] = scan.nextInt();
}
for (int i = 0; i < item; i++) {
for (int j = 0; j < days; j++) {
arr[i][j] = scan.nextInt();
}
}
int profit = 0;
for (int i = 0; i < item; i++) {
profit += helper(arr[i], maxNum[i]);
// System.out.println("current profit " + i + " is: " + profit);
}
System.out.print(profit);
}
public static int helper(int[] prices, int num) {
int min = prices[0];
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > min) {
profit += (prices[i] - min) * num;
min = prices[i];
} else {
min = prices[i];
}
}
return profit;
}
}
第三题: 匿名信
题目描述
电视剧《分界线》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字减下来,剪拼成匿名信。
现在又一名举报人,希望借鉴这种手段,使用英文报刊完成举报操作。
但为了增加文章的混淆度,只需满足每个单词中字母数量一致即可,不关注每个字母的顺序。解释:单词on允许通过单词no进行替代。
报纸代表newspaper,匿名信代表anonymousLetter,求报纸内容是否可以拼成匿名信。
输入
第一行输入newspaper内容,包括1-N个字符串,用空格分开
第二行输入anonymousLetter内容,包括1-N个字符串,用空格分开
.newspaper和anonymousLetter的字符串由小写英文字母组成,且每个字母只能使用一次
.newspaper内容中的每个字符串字母顺序可以任意调整,但必须保证字符串的完整性(每个字符串不能有多余字母) .1 < N < 100,
1 <= newspaper.length,anonymousLetter.length <= 10^4
输出
如果报纸可以拼成匿名信返回true,否则返回false
样例输入
ab cd ab
样例输出
true
public class test2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] rew = scanner.nextLine().split(" "); // newspaper去除空格
String[] let = scanner.nextLine().split(" "); // anonymousLetter
int flg = 0; //设置一个标识
for (int i = 0; i < let.length; i++) {
for (int j = 0; j < rew.length; j++) {
String a =sortString(rew[j]); //调用sortString 方法给字符串排序
String b = sortString(let[i]);
if (b.length() == a.length() && b.contains(a) )
flg ++; // 只要匿名信中元素在newspaper出现过就 +1
}
}
System.out.println(flg == let.length ? true : false);
}
public static String sortString(String s) {
char[] charArray = s.toCharArray(); //传换成char数组类型
Arrays.sort(charArray);
return new String(charArray);
}
}
第四题: 磁盘容量排序
题目描述
磁盘的容量单位常用的有M,G,T这三个等级,它们之间的换算关系为1T = 1024G,1G = 1024M,
现在给定n块磁盘的容量,请对它们按从小到大的顺序进行稳定排序,
例如给定5块盘的容量,1T,20M,3G,10G6T,3M12G9M排序后的结果为20M,3G,3M12G9M,1T,10G6T。
注意单位可以重复出现,上述3M12G9M表示的容量即为3M+12G+9M,和12M12G相等。 输入 输入第一行包含一个整数n(2 <= n
<= 100),表示磁盘的个数, 接下的n行,每行一个字符串(长度大于2,小于30),表示磁盘的容量,
由一个或多个格式为mv的子串组成,其中m表示容量大小,v表示容量单位, 例如20M,1T,30G,10G6T,3M12G9M。
磁盘容量m的范围为1到1024的正整数,容量单位v的范围只包含题目中提到的M,G,T三种,换算关系如题目描述。
输出
输出n行,表示n块磁盘容量排序后的结果。
样例输入
3
1G
2G
1024M
样例输出
1G
1024M
2G
import java.util.Scanner;
public class nB {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = Integer.parseInt(scanner.nextLine());
String[] list = new String[num];
for (int i = 0; i < num; i++) {
list[i] = scanner.nextLine();
}
// 冒泡排序
for (int i = 0; i < list.length - 1; i++) {
for (int j = 0; j < list.length - 1 - i; j++) {
if (unitCovert(list[j]) > unitCovert(list[j + 1])) {
String tem = list[j];
list[j] = list[j + 1];
list[j + 1] = tem;
}
}
}
for (String s : list) {
System.out.println(s);
}
}
// 单位换算
private static int unitCovert(String string) {
if (string.length() < 1) {
return 0;
}
int end = string.length() - 1;
int value = Integer.parseInt(string.substring(0, end));
if (string.endsWith("T")) {
return value * 1000000;
} else if (string.endsWith("G")) {
return value * 1000;
} else {
return value;
}
}
}
第五题: 高效的任务规划
题目描述
你有 n 台机器编号为 1~n,每台都需要完成完成一项工作,机器经过配置后都能完成独立完成一项工作。 假设第 i 台机器你需要花 B
分钟进行设置,然后开始运行,J 分钟后完成任务。 现在,你需要选择布置工作的顺序,使得用最短的时间完成所有工作。
注意,不能同时对两台进行配置,但配置完成的机器们可以同时执行他们各自的工作。 输入 第一行输入代表总共有 M 组任务数据(1<M<=10)。
每组数第一行为一个整数指定机器的数量 N(0<N<=1000)。 随后的 N 行每行两个整数,第一个表示
B(0<=B<=10000),第二个表示 J(0<=J<=10000)。 每组数据连续输入,不会用空行分隔。各组任务单独计时。
输出
对于每组任务,输出最短完成时间,且每组的结果独占一行。例如,两组任务就应该有两行输出。
样例输入
1
1
2 2
样例输出
4
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numCases = scanner.nextInt(); // 总共有多少组任务
for (int i = 0; i < numCases; i++) {
int numMachines = scanner.nextInt(); // 机器的数量
int totalTime = 0; // 总共所需时间
for (int j = 0; j < numMachines; j++) {
int setupTime = scanner.nextInt(); // 设置时间
int jobTime = scanner.nextInt(); // 任务完成时间
totalTime = Math.max(totalTime, setupTime + jobTime); // 取最长时间
}
System.out.println(totalTime);
}
scanner.close();
}
}
第六题:最大平分数组
题目描述
给定一个数组nums,可以将元素分为若干个组,使得每组和相等,求出满足条件的所有分组中,最大的平分组个数。 输入 第一行输入 m
接着输入m个数,表示此数组
数据范围:1<=M<=50, 1<=nums[i]<=50
输出 最大的平分组数个数。
样例输入
7
4 3 2 3 5 2 1
样例输出
4
import java.util.ArrayList;
import java.util.Scanner;
class Main {
//数组容器
public static int[] nums;
//数组选择记录
public static boolean[] choose;
//数组元素总和
public static int sum;
//搜索结果(sum是否可以被分为和为des的若干子数组)
public static boolean falg = false;
//满足条件的最小因数
public static int minFactor;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int size = Integer.parseInt(in.nextLine());
nums = new int[size];
choose = new boolean[size];
//获取数组和sum
String[] strings = in.nextLine().split(" ");
for (int i = 0; i < strings.length; i++) {
nums[i] = Integer.parseInt(strings[i]);
sum += nums[i];
}
//获取sum的因数(不需要sum自身)
ArrayList<Integer> factors = new ArrayList<>();
for (int i = 1; i <= sum/2; i++) {
if (sum % i == 0) {
factors.add(i);
}
}
//可优化:有大于des的元素可以直接判定false
//遍历由小到大寻找符合条件的因数
falg = false;
for (int i = 0; i < factors.size(); i++) {
dfs(0, factors.get(i), 0, 0);
if (falg) {
minFactor = factors.get(i);
break;
}
}
//如果没有找到符合的因数,那么答案就是sum本身(只分一组)
if (minFactor == 0) {
minFactor = sum;
}
System.out.println(minFactor);
}
/**
* 遍历各种组合判断是否可以按目标和分组
* 调用之前应先验证目标元素可行(先验证des是sum的一个因数)
* 至少两等分再调用,1等分不要调用,直接出结果
* @param index 当前索引
* @param des 子数组目标元素和
* @param countI 当前子数组组号
* @param countD 当前子数组当前元素和
*/
public static void dfs(int index,int des,int countI,int countD) {
//当本组元素和没达到目标时
if (index < choose.length && !choose[index] && countD < des) {
//选取当前元素
choose[index] = true;
dfs(index + 1, des, countI, countD + nums[index]);
//不选取当前元素
choose[index] = false;
dfs(index + 1, des, countI, countD);
} else if (countD == des) {//当恰好达到目标时
//当倒数第二组组合完成,倒数第一组不需验证,直接通过
if (countI == sum / des - 2) {
falg = true;
} else if (countI < sum / des - 2) {
int start = -1;
for (int i = 0; i < choose.length; i++) {
if (!choose[i]) {
start = i;
break;
}
}
if (start == -1) {
return;
}
dfs(start, des, countI + 1, 0);
}
}
}
}