【问题标题】:My code is giving a wrong answer in codechef我的代码在 codechef 中给出了错误的答案
【发布时间】:2018-11-12 22:51:18
【问题描述】:

我的代码在我的编译器中运行良好,我什至尝试了其他几个在线编译器,但仍然无法找到问题,谁能帮忙!

问题

https://www.codechef.com/JUNE18B/problems/NAICHEF

有一次,在紧张了一天之后,Chef 决定放松一下,去他家附近的一家赌场赌博。他觉得自己很幸运,他将赌上几乎所有的钱。

Chef 将在赌场玩的游戏是用 N 掷骰子 面对两次。骰子的每个面上都有一个数字(这些数字不一定不同)。为了获胜,Chef 必须获得数字 A 在第一次投掷和数字 B 在第二次掷骰子时。

激动的观众想知道大厨赢得比赛的概率。你能帮他们找到那个号码吗?假设 Chef 在每次投掷时以相同的概率获得骰子的每张面,并且投掷是相互独立的。

我的提交

import static java.lang.System.exit;
import java.util.*;
import java.lang.*;

/**
 *
 * @author williamscott
 */
public class Main {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        boolean status = true;

        int T = Integer.parseInt(in.nextLine());

        //Original Constraint
        if (T < 1 || T > 10) {
//            System.out.println("Please follow original constraint for T");
//            exit(0);
            status = false;
        }

        int N[] = new int[T], A[] = new int[T], B[] = new int[T];
        float Probability[] = new float[T];

        for (int t = 0; t < T; t++) {

            String[] input = in.nextLine().split(" ");

            N[t] = Integer.parseInt(input[0]);
            A[t] = Integer.parseInt(input[1]);
            B[t] = Integer.parseInt(input[2]);

            if (N[t] < 1 || N[t] > 100) {
//                System.out.println("Please follow original constraint for N");
//                exit(0);
                status = false;
            }

            if (A[t] < 1 || A[t] > N[t]) {
//                System.out.println("Please follow original constraint for A");
//                exit(0);
                status = false;

            }

            if (B[t] < 1 || B[t] > N[t]) {
//                System.out.println("Please follow original constraint for B");
//                exit(0);
                status = false;
            }

            float pn, pa = 0, pb = 0;

            String[] f = in.nextLine().split(" ");
            pn = f.length;

            if (pn != N[t]) {
//                System.out.println("Inputs Invalid");
//                exit(0);
                status = false;
            }

            for (String f1 : f) {

                if (Integer.parseInt(f1) < 1 || Integer.parseInt(f1) > N[t]) {
//                    System.out.println("Please follow original constraint for x (input)");
//                    exit(0);
                    status = false;
                }

                if (Integer.parseInt(f1) == A[0]) {
                    pa++;
                }
                if (Integer.parseInt(f1) == B[0]) {
                    pb++;
                }
            }

            Probability[t] = (pa / pn) * (pb / pn);
        }

        if (status) {
            for (float d : Probability) {
                System.out.println(String.format("%.10f", d));
            }
        }

    }

}

错误:

【问题讨论】:

  • 将作业的相关部分以及您的代码发布到问题中,并清楚地说明您的代码输出错误结果的输入以及正确的结果应该是什么。
  • @luk2302 感谢您的快速回复,我更新了问题...
  • 感谢您对问题的改进 -- 删除了反对票和近距离投票。我没有时间浏览代码,但有几个建议:避免使用浮点数进行==!=,因为这些比较不适用于浮点的不精确表示。相反,这些数字可能应该是整数。当您通过强制转换在概率计算中进行除法时,您需要将它们转换为双精度,但在您绝对需要双精度之前将它们保留为整数。
  • 顺便说一句,你会想学习和使用Java naming conventions。变量名应全部以小写字母开头,而类名应以大写字母开头。学习这一点并遵循这一点将使我们更好地理解您的代码,并使您更好地理解他人的代码。
  • 另外从不在双精度工作时使用浮点数。否则,您会损失很多精度而收获很少。

标签: java error-handling compiler-errors


【解决方案1】:
  1. 从不使用==!= 比较浮点数。数字计算机无法以绝对精度表示浮点数,因此这些测试通常会失败。
  2. 从不double 有效时使用 float。使用浮点数获得的收益很少,但会损失很大的精度。
  3. 将整数输入保留为ints,仅在需要时转换为double,此处在进行概率计算时转换为double
  4. 不要像您正在做的那样过度复杂化您的代码,并使用可测试的方法来帮助简化。例如,无需使用数组。上面提到的约束可能不需要在您的程序中进行测试,而是假设为真的。
  5. 使用符合 Java 命名标准且有意义的变量名。

例如:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // get number of trys
        String line = scanner.nextLine();
        int trys = Integer.parseInt(line.trim());
        for (int i = 0; i < trys; i++) {
            // for each try, calc probability
            double probability = processTry(scanner);
            System.out.println(probability);
        }
        scanner.close();
    }

    private static double processTry(Scanner scanner) {
        String line;
        // get first line
        line = scanner.nextLine();

        // use Scanner to get ints from line
        Scanner lineScan = new Scanner(line);

        //number of faces
        int numberOfFaces = lineScan.nextInt();
        int a = lineScan.nextInt();
        int b = lineScan.nextInt();
        lineScan.close();

        // scanner to get face values
        line = scanner.nextLine();
        lineScan = new Scanner(line);

        // count of how many faces match a and b values
        int aMatch = 0;
        int bMatch = 0;
        for (int i = 0; i < numberOfFaces; i++) {
            int face = lineScan.nextInt();
            if (a == face) {
                aMatch++;
            } 
            if (b == face) {
                bMatch++;
            }
        }
        lineScan.close();

        // only cast to double when need for calc
        double probability = ((double) (aMatch * bMatch) / (numberOfFaces * numberOfFaces));
        return probability;
    }
}

【讨论】:

    【解决方案2】:

    首先,您应该使用 double 而不是 float(精度很重要)!

    其次,你应该更新你的状态条件,因为你只考虑第一个子任务(T小于10,N小于100),这只会给你20分!第二个子任务(奖励 80 分)的 T 小于 70,N 小于 1000。

    最后,代码的问题来自更新pa和pb的条件,你使用:

        Integer.parseInt(f1) == A[0]  // same for B[0]
    

    而不是

        Integer.parseInt(f1) == A[t]  // same for B[t]
    

    这里是完整的代码和提交结果

        import java.util.*;
        import java.lang.*;
    
        /**
         *
         * @author aoubidar
         */
        public class Main {
    
            public static void main(String[] args) {
    
                Scanner in = new Scanner(System.in);
    
                // number of test cases
                int T = Integer.parseInt(in.nextLine());
    
    
                int[] N = new int[T];
                int[] A = new int[T];
                int[] B = new int[T];
    
                double[] Probability = new double[T];
    
                for (int t = 0; t < T; t++) {
    
                    String[] input = in.nextLine().split(" ");
    
                    N[t] = Integer.parseInt(input[0]);
                    A[t] = Integer.parseInt(input[1]);
                    B[t] = Integer.parseInt(input[2]);
    
                    int total, pa = 0, pb = 0 ;
    
                    String[] faces = in.nextLine().split(" ");
                    total = faces.length;
    
                    for (String f : faces) {
    
                        if (Integer.parseInt(f) == A[t]) {
                            pa++;
                        }
                        if (Integer.parseInt(f) == B[t]) {
                            pb++;
                        }
                    }
    
                    double pn = (double) (total * total);
    
                    Probability[t] = (pa * pb) / pn ;
                }
    
                for (double d : Probability) {
                    System.out.println(d);
                }
    
    
            }
    
        } 
    

    提交成功:

    【讨论】:

    • 非常好的捕捉和解释。 1+ 到这个答案
    • 非常感谢您的努力,不久前我想出了这个,我正要发布我的最终答案......我完全忘记发布答案涉及另一个问题。您的建议“当双精度有效时,也不要使用浮点数。否则,您会损失很多精度而收益很少。”帮助,我实际上注意到浮动给出了不准确的值。我将其更改为浮动并进行了测试,我发现循环计数也发生了变化......再次非常感谢......
    【解决方案3】:

    假设 n(A) 是 A 在骰子上出现的次数,n(B) 是 B 在骰子上出现的次数。其中,A 在给定时间被抛出的概率为

    P(A) = n(A) / N

    B 在给定时间被抛出的概率是

    P(B) = n(B) / N

    A先被抛出,B后被抛出的概率为

    P(A) ^ P(B) = P(A) * P(B)

    因为实验是独立的。

    P(A) * P(B) = n(A) * n(B) / N^2

    由于这正是在您的代码中,因此您已经为计算实现了正确的算法,因此问题必须出在算法之外的其他东西上。

    浮点数的使用

    使用 float 可能会导致您的结果与预期结果之间存在细微差别。将其更改为双倍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      相关资源
      最近更新 更多