zoukankan      html  css  js  c++  java
  • ACM 新手入门 之 如何实现多组输入输出

    一般ACM赛制题目都要求  多组输入输出 ,我们以 杭电1000题为例:

    题目是很简单的 A+B :代码为:

    #include<stdio.h>
    int main()
    {
    	int a,b;
    	scanf("%d%d",&a,&b); 
    	printf("%d
    ",a+b);
    	return 0;
    }

    但是要求的是多组输入输出,所以上面的代码就不对,得加上这个: 

    #include<stdio.h>
    int main()
    {
    	int a,b;
    	
    	while (scanf("%d%d",&a,&b) != EOF)// 一律用这种写法,把你的scanf函数写成这样子,除了return 0之外,其他的语句都要用大括号括起来 
    	{
    		printf("%d
    ",a+b);
    	} 
    	
    	return 0;
    }

    这样就是简单实现多组输入输出了。对于其他的各种输入输出类型,下面再来介绍:

    ACM题目特点: 由于ACM竞赛题目的输入数据和输出数据一般有多组(不定),并且格式多种多样,所以,如何处理题目的输入输出是对大家的一项最基本的要求。这也是困扰初学者的一大问题。 ACM的输入输出要求严格按照规定来,所以你不需要输出像"Please input the data"这类的提示语。否则将会被判Wrong Answer。
    1、输入
    初学者一般有个误区:如果题目包含多组测试数据,他们就会把输入的内容全部保存起来,然后再依次处理。
    其实程序的输入输出是相互独立的,因此,每当处理完一组测试数据,就应当按题目要求进行相应的输出操作。而不必将所有结果储存起来一起输出。
    下面来介绍一下ACM中常见的一些输入情况。

    只有一组测试数据
    这类题目是最简单的,比如第1000题。(http://acm.hdu.edu.cn/showproblem.php?pid=1000)参考代码:
    #include
    int main(void)
    {
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d ", a + b);
    return 0;
    }

    没有明确指出输入什么时候结束
    如果是这种情况,我们默认是以“文件结束”(EOF)为结束标志。
    这是ACM的默规,例如1076(
    http://acm.hdu.edu.cn/showproblem.php?pid=1076)题。参考代码:
    #include
    int main(void)
    {
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF)
    printf("%d ", a + b);
    return 0;
    }

    指定数据量
    有时会在数据的第一行提供数据量大小,比如第一行是100,则表示有100组数据。比如第1077题。()参考代码:
    #include
    int main(void)
    {
    int n, a, b;
    scanf("%d", &n);
    while (n--)
    {
    scanf("%d %d", &a, &b);
    printf("%d ", a + b);
    }
    return 0;
    }

    以特定元素作结束符
    这种输入和第一种类似。常见的是规定以0作为结束符。
    比如第1078题。参考代码:

    #include
    int main(void)
    {
    int a, b;

    while (scanf("%d %d", &a, &b), a || b)
    printf("%d ", a + b);

    return 0;
    }


    输出

    输出格式统一
    这种比较简单,只要按要求来就没问题的。比如每组输出占一行,或者每组输出后面加一个空行。比如1000题。

    数据之间有空行
    (1)
    对于这种输出,有时候还会告诉你有几组输入,这样你就可以自己判断一下是不是最后一组。是就不输出空行,否则多输出一个空行。而有时候连共有几组数据都不会告诉你。其实不论知不知道有几组数据,我们都可以这样处理。

    (2)第一组数据后面不加空行。 第二组开始,每组前面加空行。 比如第1079题,参考代码:

    #include
    int main(void)
    {
    int a, b, i = 0;
    while (scanf("%d %d", &a, &b), a || b)
    printf((i++? " %d ": "%d "), a + b);
    return 0;
    }

    下面介绍常用的处理输入的方法

    几种常用的处理输入方法(C语言)
    感觉新人对于处理输入输出存在一些问题,这里写出几个常用到的处理方法:
    1.
    知道输入数据组数n
      scanf("%d",&n);
      whlie(n--){
         
    这里处理每一组输入.然后直接按格式输出,没必要开数组存储答案.
      }
    2.
    没有数据总数,EOF结束
      可能用的几个函数:
      scanf():
      while(scanf("%s|%d")!=EOF){
       
    处理每一组数据,并输出.
      }
      getchar():
    读入一个字符
      whlie((ch=getchar())!=EOF){
         
      }
      gets():
    读入一行
      while(gets(buf)!=NULL) {
     
      }
     
    getchar,gets注意读入换行符.
    3.
    0-1结束的输入.
      while(scanf("%d",&n),n!=0) {
     
      } 

    C++  及 JAVA 的多组输入输出:

    关于C++的输入输出处理:

    cin读字符串时遇到空白符(空格,换行等)结束
    char str[BUFFER];
    while (cin >> str) {
    }
    getline
    读字符串时遇到换行符结束,用于读一整行
    char str[BUFFER];
    while (cin.getline(str, BUFFER)) {
    }
    string str;
    while (getline(cin, str)) {
    }

    cin/cout
    要比scanf/printf慢一些,尽可能使用scanf/printf以避免测试大量数据时因为输入输出慢而导致TLE. putchar/getchar要比scanf/printf更快
     

    关于java的输入输出处理:

    如果使用BufferedReader(jdk1.1或以后的版本,一次读一整行字符串,类似于gets)
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    String s;
    while ((s = stdin.readLine()) != null) {
       
    可以用StringTokenizer st = new StringTokenizer(s);来按空格切词
        int n = Integer.parseInt(st.nextToken());
        double b = Double.parseDouble(st.nextToken());
    }

       
    如果使用Scanner(仅限于jdk1.5或以后的版本,一般用于从字符串中切词,类似于cin)
    Scanner stdin = new Scanner(System.in);
    while (stdin.hasNext()) {
        String s = stdin.next();
        int n = stdin.nextInt();
        double b = stdin.nextDouble();
    }

       
    至于输出,很多新手总会选择先将答案存储在一个数组里,等程序运行完再输出,其实这是没有必要的,机器判决是逐个字符匹配,所以完全可以处理一组输入后,便输出结果。

     JAVA 心得 :

    ACM采用Java语言心得

     

    Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点:

    (1) 最明显的好处是,学会Java,可以参加Java Challenge 。

    (2) 对于熟悉C/C++的程序员来说,Java 并不难学,找本书,一两周业余时间就可以搞定了。当然,这里只是指一般编程,想熟悉所有的Java库还是需要些时间的。事实上,Java 只相当于C++的一个改进版,所有的语法都几乎是C++的,很少有变动。

    (3) 在一般比赛中,Java程序会有额外的时间和空间,而实际上经过实验,在执行计算密集任务的时候Java并不比C/C++慢多少,只是IO操作较慢而已。

    (4) Java 简单而功能强大,有些东西用Java实现起来更为方便,比如高精度。

    (5) 用Java不易犯细微的错误,比如C/C++中的指针, “if (n = m) ... ” 等。

    (6) 目前来看Eclipse已成基本配置,写Java程序反而比C/C++更方便调试。在具体竞赛时也算多一种选择。

    (7) 学会Java对以后工作有好处。现在国外很多地方会Java的人比会C/C++的人多。

    (8) 会Java可以使你看起来更像偶蹄类动物(牛)。

     

    下面说一下ACM-ICPC队员初用Java编程所遇到的一些问题:

    1、基本输入输出:

    (1) JDK 1.5.0 新增的Scanner类为输入提供了良好的基础,简直就是为ACM-ICPC而设的。

    一般用法为:

    import java.io.*

    import java.util.*

     

    public class Main

    {

    public static void main(String args[])

    {

    Scanner cin = new Scanner(new BufferedInputStream(System.in));

    ...

    }

    }

     

    当然也可以直接 Scanner cin = new Scanner(System.in);

    只是加Buffer可能会快一些

    (2)

    读一个整数:int n = cin.nextInt(); 相当于 scanf("%d", &n); 或 cin >> n;

    读一个字符串:String s = cin.next(); 相当于 scanf("%s", s); 或 cin >> s;

    读一个浮点数:double t = cin.nextDouble(); 相当于 scanf("%lf", &t); 或 cin >> t;

    读一整行: String s = cin.nextLine(); 相当于 gets(s); 或 cin.getline(...);

    判断是否有下一个输入可以用 cin.hasNext() 或 cin.hasNextInt() 或 cin.hasNextDouble() 等,具体见 TOJ 1001 例程。

    (3)

    输出一般可以直接用 System.out.print() 和 System.out.println(),前者不输出换行,而后者输出。

    比如:

    System.out.println(n);   // n 为 int 型

    同一行输出多个整数可以用

    System.out.println(new Integer(n).toString() + " " + new Integer(m).toString());

    也可重新定义:

    static PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));    

    cout.println(n);

    (4)

    对于输出浮点数保留几位小数的问题,可以使用DecimalFormat类,

    import java.text.*;

    DecimalFormat f = new DecimalFormat("#.00#");

    DecimalFormat g = new DecimalFormat("0.000");

    double a = 123.45678, b = 0.12;

    System.out.println(f.format(a));

    System.out.println(f.format(b));

    System.out.println(g.format(b));

    这里0指一位数字,#指除0以外的数字。

    2、大数字

    BigInteger 和 BigDecimal 是在java.math包中已有的类,前者表示整数,后者表示浮点数

    用法:

    不能直接用符号如+、-来使用大数字,例如:

    (import java.math.*)   // 需要引入 java.math 包

    BigInteger a = BigInteger.valueOf(100);

    BigInteger b = BigInteger.valueOf(50);

    BigInteger c = a.add(b)   // c = a + b;

    主要有以下方法可以使用:

    BigInteger add(BigInteger other)

    BigInteger subtract(BigInteger other)

    BigInteger multiply(BigInteger other)

    BigInteger divide(BigInteger other)

    BigInteger mod(BigInteger other)

    int compareTo(BigInteger other)

    static BigInteger valueOf(long x)

    输出大数字时直接使用 System.out.println(a) 即可。

    3、字符串

    String 类用来存储字符串,可以用charAt方法来取出其中某一字节,计数从0开始:

    String a = "Hello";    // a.charAt(1) = 'e'

    用substring方法可得到子串,如上例

    System.out.println(a.substring(0, 4))     // output "Hell"

    注意第2个参数位置上的字符不包括进来。这样做使得 s.substring(a, b) 总是有 b-a个字符。

    字符串连接可以直接用 + 号,如

    String a = "Hello";

    String b = "world";

    System.out.println(a + ", " + b + "!");    // output "Hello, world!"

    如想直接将字符串中的某字节改变,可以使用另外的StringBuffer类。

    4、调用递归(或其他动态方法)

    在主类中 main 方法必须是 public static void 的,在 main 中调用非static类时会有警告信息,

    可以先建立对象,然后通过对象调用方法:

    public class Main

    {

    ...

    void dfs(int a)

    {

    if (...) return;

    ...

    dfs(a+1);

    }

    public static void main(String args[])

    {

    ...

    Main e = new Main();

    e.dfs(0);

    ...

    }

    }

    5、其他注意的事项

    (1) Java 是面向对象的语言,思考方法需要变换一下,里面的函数统称为方法,不要搞错。

    (2) Java 里的数组有些变动,多维数组的内部其实都是指针,所以Java不支持fill多维数组。

    数组定义后必须初始化,如 int[] a = new int[100];

    (3) 布尔类型为 boolean,只有truefalse二值,在 if (...) / while (...) 等语句的条件中必须为boolean类型。

    C/C++中的 if (n % 2) ... Java中无法编译通过。

    (4) 下面在java.util包里Arrays类的几个方法可替代C/C++里的memsetqsort/sort bsearch:

    Arrays.fill()

    Arrays.sort()

    Arrays.binarySearch()  

    Q:系统返回信息都是什么意思?
    A:详见下述:

    Pending : 系统忙,你的答案在排队等待.

    Pending Rejudge: 因为数据更新或其他原因,系统将重新判你的答案.

    Compiling : 正在编译.

    Running & Judging: 正在运行和判断.

    Accepted : 程序通过!

    Presentation Error : 答案基本正确,但是格式不对。

    Wrong Answer : 答案不对,仅仅通过样例数据的测试并不一定是正确答案,一定还有你没想到的地方.

    Time Limit Exceeded : 运行超出时间限制,检查下是否有死循环,或者应该有更快的计算方法。

    Memory Limit Exceeded : 超出内存限制,数据可能需要压缩,检查内存是否有泄露。

    Output Limit Exceeded: 输出超过限制,你的输出比正确答案长了两倍.

    Runtime Error : 运行时错误,非法的内存访问,数组越界,指针漂移,调用禁用的系统函数。请点击后获得详细输出。

    Compile Error : 编译错误,请点击后获得编译器的详细输出。
     

    不用谢,请叫我雷锋!QWQ 

  • 相关阅读:
    Java实现 LeetCode 413 等差数列划分
    Java实现 LeetCode 413 等差数列划分
    Java实现 LeetCode 412 Fizz Buzz
    简单字符设备驱动程序
    fork与vfork的区别
    进程创建函数fork()、vfork() ,以及excel()函数
    区分execl与system——应用程序中执行命令
    CMOS Sensor的调试经验分享
    嵌入式ARM-Linux开发工具下载地址合集
    嵌入式 linux 查看内存
  • 原文地址:https://www.cnblogs.com/Romantic-Chopin/p/12451384.html
Copyright © 2011-2022 走看看