大家都知道,有些题目只有测试样例。

大家又都知道,有些题目有人打表。

大家㕛都知道,出数据很难。

大家叒都知道,防止打表更难。

大家叕不知道,有一种技术叫做全自动对拍可以解决这个问题。

全自动对拍:

顾名思义,所有输入数据均为符合格式的随机数,评测程序(std)和你的程序输出的结果一致就AC,否则WA

示范例子:http://43.139.175.183/p/16

我将展示我是如何出这道题的对拍的:

首先,某些人打表,我受不了,准备加上全自动对拍。

接着,要先写出STD标准代码:

#include <iostream>
#include <cmath>
using namespace std;
bool a[1001][1001];
int main(){
    int x,y;
    cin >> x >> y;
    int n;
    cin >> n;
    int cnt = 0;
    for (int i = 1;i<=n;i++){
        int tx,ty;cin >> tx >> ty;
        for (int j = -4;j<=4;j++){
            for (int k = -4;k<=4;k++){//偏移量
                if (tx+j<=0||ty+k<=0||tx+j>x||ty+k>y) continue;
                if (abs(j)+abs(k)<=4&&a[j+tx][k+ty]==false){//判断是否能被灌溉到
                    cnt++;
                    a[tx+j][ty+k]=true;
                    //cout << tx+j << " " << ty+k << endl;
                }
            }
        }
    }
    cout << cnt;
    return 0;
}

接着就是写一段数据生成和对拍器:

先写个随机数:

#include "testlib.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
    setName("Interactor watering");
    registerInteraction(argc, argv);
    // //自动生成两个随机整数
    rnd.setSeed(time(NULL));
    int x = rnd.next(1000);
    int y = rnd.next(1000);
    int n = rnd.next(1000);
    cout << x << " " << y << endl << n << endl;
    int cnt = 0;
    for (int i = 1;i<=n;i++){
        int tx=rnd.next(1000);
        int ty=rnd.next(1000);
        cout << tx << " " << ty << endl;
    }
    cout << endl;
}

这里解释一下最后输出endl的意义:因为testlib的输入输出不会自动刷新缓冲区,所以我们要输出一个endl手动刷新。(cout << flush();好像也可以)(当时被这个问题困惑了老半天,想了半天觉得是缓冲区的锅,然后加了endl就好了)

接着加上生成标准答案的部分:

#include "testlib.h"
#include <iostream>
using namespace std;
bool a[1001][1001];
int main(int argc, char* argv[]) {
    setName("Interactor watering");
    registerInteraction(argc, argv);
    // //自动生成两个随机整数
    rnd.setSeed(time(NULL));
    int x = rnd.next(1000);
    int y = rnd.next(1000);
    int n = rnd.next(1000);
    cout << x << " " << y << endl << n << endl;
    int cnt = 0;
    for (int i = 1;i<=n;i++){
        int tx=rnd.next(1000);
        int ty=rnd.next(1000);
        cout << tx << " " << ty << endl;
        for (int j = -4;j<=4;j++){
            for (int k = -4;k<=4;k++){
                if (tx+j<=0||ty+k<=0||tx+j>x||ty+k>y) continue;
                if (abs(j)+abs(k)<=4&&a[j+tx][k+ty]==false){
                    cnt++;
                    a[tx+j][ty+k]=true;
                }
            }
        }
    }
    cout << endl;
    int ans;
    cin >> ans;
}

加上比较:

#include "testlib.h"
#include <iostream>
using namespace std;
bool a[1001][1001];
int main(int argc, char* argv[]) {
    setName("Interactor watering");
    registerInteraction(argc, argv);
    // //自动生成两个随机整数
    rnd.setSeed(time(NULL));
    int x = rnd.next(1000);
    int y = rnd.next(1000);
    int n = rnd.next(1000);
    cout << x << " " << y << endl << n << endl;
    int cnt = 0;
    for (int i = 1;i<=n;i++){
        int tx=rnd.next(1000);
        int ty=rnd.next(1000);
        cout << tx << " " << ty << endl;
        for (int j = -4;j<=4;j++){
            for (int k = -4;k<=4;k++){
                if (tx+j<=0||ty+k<=0||tx+j>x||ty+k>y) continue;
                if (abs(j)+abs(k)<=4&&a[j+tx][k+ty]==false){
                    cnt++;
                    a[tx+j][ty+k]=true;
                }
            }
        }
    }
    cout << endl;
    int ans;
    cin >> ans;
    if (cnt != ans)
        quitf(_wa, "你这个测试点没过,试试样例能不能过吧!",n,x,y);
    else
        quitf(_ok, "这个测试点过了!",n,x,y);
}

就成功解决了对拍程序(一般叫做checker.cc

最后是config文件填写: (照着抄就行了。。。)

type: interactive
interactor: checker.cc
subtasks:
  - score: 100
    type: sum
    cases:
      - input: /dev/null
        output: /dev/null
      - input: /dev/null
        output: /dev/null
      - input: /dev/null
        output: /dev/null

解释一下每一行:

类型:自动对拍
对拍程序:checker.cc
数据点:
-分值100的:
 求分方式:求和
 数据:
       -输入:没有输入文件,对拍程序自动生成
         输出:没有输出文件,对拍程序自动生成
       -输入:没有输入文件,对拍程序自动生成
         输出:没有输出文件,对拍程序自动生成
       -输入:没有输入文件,对拍程序自动生成
         输出:没有输出文件,对拍程序自动生成
#输入输出有n组就代表有n个测试点

目前有个随机数的bug,就是testlib的随机数每次测试都一样,站长近期将进入其他随机生成器解决

Update:

感谢的帮助,已经有新的随机数生成器可以解决上述问题了。

新版随机数生成器需要的头文件:

#include <random>

新版随机数初始化:

random_device rd;
mt19937 myrand(rd());
uniform_int_distribution<> u(1, 1000);//括号内的数是随机数的范围,例如1-114514就是uniform_int_distribution<> u(1, 114514);

新版随机数使用:

u(myrand)
//返回一个int类型的随机数,范围在为初始化时的范围

新版对拍程序:

#include "testlib.h"
#include <iostream>
#include <random>
using namespace std;
bool a[1001][1001];
int main(int argc, char* argv[]) {
    setName("Interactor watering BETA");
    registerInteraction(argc, argv);
    random_device rd;
    mt19937 myrand(rd());
    uniform_int_distribution<> u(1, 1000);
    int cnt = 0;
    int x = u(myrand);
    int y = u(myrand);
    int n = u(myrand);
    cout << x << " " << y << endl << n << endl;
    cnt = 0;
    for (int i = 1;i<=n;i++){
        int tx=u(myrand);
        int ty=u(myrand);
        cout << tx << " " << ty << endl;
        for (int j = -4;j<=4;j++){
            for (int k = -4;k<=4;k++){
                if (tx+j<=0||ty+k<=0||tx+j>x||ty+k>y) continue;
                if (abs(j)+abs(k)<=4&&a[j+tx][k+ty]==false){
                    cnt++;
                    a[tx+j][ty+k]=true;
                }
            }
        }
    }
    cout << endl;
    int ans;
    cin >> ans;
    if (cnt != ans)
        quitf(_wa, "你这个测试点没过,试试样例能不能过吧!");
    else
        quitf(_ok, "这个测试点过了!调试信息:n=%d x=%d y=%d",n,x,y);
}

2 条评论

  • @ 2023-6-2 21:25:08

    bpoj有全自动对拍,用mt19937就可以。

    • @ 2023-6-3 8:47:23

      谢谢指导,问一下随机种子怎么解决?我用了mt还是不行,每次都一样

    • @ 2023-6-3 8:49:23

      http://43.139.175.183/p/89

      在这里测试的

    • @ 2023-6-3 8:51:14

      checker:

      #include "testlib.h"
      #include <iostream>
      #include <random>
      #include <ctime>
      using namespace std;
      bool a[1001][1001];
      int main(int argc, char* argv[]) {
          setName("Interactor watering");
          registerInteraction(argc, argv);
          // //自动生成两个随机整数
          mt19937 myrand(114514);//time(0)也试过了,不行
          int cnt = 0;
          int x = myrand()%1000;
          int y = myrand()%1000;
          int n = myrand()%1000;
          cout << x << " " << y << endl << n << endl;
          cnt = 0;
          for (int i = 1;i<=n;i++){
              int tx=myrand()%1000;
              int ty=myrand()%1000;
              cout << tx << " " << ty << endl;
              for (int j = -4;j<=4;j++){
                  for (int k = -4;k<=4;k++){
                      if (tx+j<=0||ty+k<=0||tx+j>x||ty+k>y) continue;
                      if (abs(j)+abs(k)<=4&&a[j+tx][k+ty]==false){
                          cnt++;
                          a[tx+j][ty+k]=true;
                      }
                  }
              }
          }
          cout << endl;
          int ans;
          cin >> ans;
          if (cnt != ans)
              quitf(_wa, "你这个测试点没过,试试样例能不能过吧!");
          else
              quitf(_ok, "这个测试点过了!调试信息:n=%d x=%d y=%d",n,x,y);
      }
      
    • @ 2023-6-3 8:56:20

      请问一下贵站的全自动对拍可以给个范例checker吗?

    • @ 2023-6-3 8:59:43

      @

      抱歉说错了,我用的uniform_int_distribution

      部分代码:

      uniform_int_distribution<> u(1, 100000);
      int tn = u(gen);
      cout << tn << endl;
      
  • @ 2023-6-2 20:59:00

    我看不懂...

  • 1