如题
最近有点忙(JavaWeb好烦),所以有段时间没有做题了,正好发现了一道漏做的HDOJ第11页上的靠前的题目,做个分析整理来帮助我调整状态
下面是java代码,里面有一些我调试时的无用代码,已经注释掉了。只是想抄的同学面向CV编程一波就可以走了,再下面是详解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
while (kb.hasNext()) {
int n = kb.nextInt(), m = kb.nextInt();
one(kb, n, m);
System.out.println();
}
}
public static void one(Scanner kb, int n, int m) {
double[][] a = new double[n][m];
int[] b = new int[n];
int check = 0;
for (int i = 0; i < n; i++) { //录入分数
for (int j = 0; j < m; j++) {
a[i][j] = kb.nextDouble();
}
}
for (int i = 0; i < n; i++) {
double c = 0;
b[i] = 1;
for (int j = 0; j < m; j++) {
c += a[i][j];
}
c /= m;
if (check == 1) System.out.print(" ");
System.out.printf("%.2f", c);
check = 1;
}
System.out.println();
check = 0;
for (int i = 0; i < m; i++) {
double c = 0;
for (int j = 0; j < n; j++) {
c += a[j][i];
}
c /= n; //每科平均
for (int j = 0; j < n; j++) {
if (b[j] == 1 && c > a[j][i]) {
// System.out.println(c + " " + a[j][i] + " " + j + " " + i);
b[j] = 0;
}
}
if (check == 1) System.out.print(" ");
System.out.printf("%.2f", c);
check = 1;
}
System.out.println();
check = 0;
for (int i : b) {
// System.out.print(" =" + i);
check += i;
}
System.out.println(check);
}
}
下面我来慢慢的分析题目
首先是有多个测试实例,所以照惯例hasNext的判断必不可少,这也是HDOJ的特色吧
然后我们可以从题目中得知每个测试实例在第一行会有两个参数,分别是代表学生数量的 n 以及代表课程数量的 m ,我们可以简单的写出读入语句。
为了防止数据和题目描述不一致(曾经我还不太会写程序时暴力写一道忘了哪里的题目时总是WA,最后发现题目描述里的数据范围有误),我是动态生成不同大小的二维数组来进行操作。
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
while (kb.hasNext()) {
int n = kb.nextInt(), m = kb.nextInt();
one(kb, n, m);
System.out.println();
}
}
在java中,主函数main里面数组定义不可以用变量,所以我把n和m传入函数中。
是所以要把Scanner对象也传进去是因为有些OJ的java在创建一个Scanner对象之后,即使销毁此对象再传参到函数,函数里面再创Scanner对象就会报错。
double[][] a = new double[n][m];
int[] b = new int[n];
int check = 0;
for (int i = 0; i < n; i++) { //录入分数
for (int j = 0; j < m; j++) {
a[i][j] = kb.nextDouble();
}
}
在函数里我定义了一个二维数组a用来存储输入的信息,一个一维数组b来计算各科成绩均大于等于平均成绩的学生数量,为了节省时间(虽说感觉也不会TLE)我在某次循环时初始化数组b减少了循环的时间。
我们知道n个人,m科,如图
1 | 2 | … | n-1 | n | |
---|---|---|---|---|---|
1 | |||||
2 | |||||
… | |||||
m-1 | |||||
m |
那么没科成绩平均数和单人成绩平均数就是一行/列的平均数,就可以简单的进行单行/单列的读取并输出,为了格式,我定义了一个int类型的check,用于判断这一行是否输出过。至于为什么用int类型而不用boolean类型,是因为check在后面会复用。
for (int i = 0; i < n; i++) {
double c = 0;
b[i] = 1;
for (int j = 0; j < m; j++) {
c += a[i][j];
}
c /= m;
if (check == 1) System.out.print(" ");
System.out.printf("%.2f", c);
check = 1;
}
System.out.println();
check = 0;
for (int i = 0; i < m; i++) {
double c = 0;
for (int j = 0; j < n; j++) {
c += a[j][i];
}
c /= n; //每科平均
for (int j = 0; j < n; j++) {
if (b[j] == 1 && c > a[j][i]) {
// System.out.println(c + " " + a[j][i] + " " + j + " " + i);
b[j] = 0;
}
}
if (check == 1) System.out.print(" ");
System.out.printf("%.2f", c);
check = 1;
}
System.out.println();
你们可以看到在计算每科平均成绩的循环里我加上了如下代码
for (int j = 0; j < n; j++) {
if (b[j] == 1 && c > a[j][i]) {
// System.out.println(c + " " + a[j][i] + " " + j + " " + i);
b[j] = 0;
}
}
这代码用来及时判断并筛选掉有单科没有过的同学,先判断是否还没有被筛选掉,再判断是否单科没有过。
最后用一个foreach来循环,计算人数
check = 0;
for (int i : b) {
check += i;
}
System.out.println(check);
看不懂foreach的同学看下面,下面代码可以代替foreach
for (int i = 0; i < n; i++) {
check += i;
}
这就是一种HDOJ 2023的解法了
本文用于备忘和分享