Windows C++程序对拍

此前写过Ubuntu下的程序对拍:https://blog.csdn.net/moon_sky1999/article/details/100353519

对拍是一种很好的纠错手段,特别是在算法竞赛中,通过对拍,可以得到有效的Debug的数据。对拍的基本原理大概如下:自己手写一个完全暴力的程序(一定要确保该代码的正确性,该代码是对拍的基础),利用这份暴力代码,与自己写的代码运行同样的数据,对比二者的结果。

举个例子:

给出一个长度为 n n n的序列 A n A_n An,求最大连续和。(注意 A i A_i Ai可能是负数)
换句话说,就是要找到 1 ≤ i ≤ j ≤ n 1≤i≤j≤n 1ijn,使得 A i + A i + 1 + … + A j A_i+A_{i+1}+…+A_j Ai+Ai+1++Aj最大。

最为暴力的做法大概是枚举所有的i,j,对每一个区间都进行求和,最终取最大值,输出。时间复杂度为 O ( n 3 ) O(n^3) O(n3)

#include 
using namespace std;

const int inf = 1e9 + 10;
int n, a[10010];

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    int ans = -inf;
    for (int i = 1; i <= n; ++i) {
        for (int j = i; j <= n; ++j) {
            int ct = 0;
            for (int k = i; k <= j; ++k)
                ct += a[k];
            ans = max(ans, ct);
        }
    }
    cout << ans << endl;
    return 0;
}

这份代码作为暴力代码,用于对比自己代码运行的结果。

假如说我们写好的代码如下:

#include 
using namespace std;

const int inf = 1e9 + 10;
int n, a[10010], s[10010];

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    int ans = 0, mx = 0, mn = 0;
    for (int i = 1; i <= n; ++i) {
        s[i] = s[i - 1] + a[i];
        mx = max(mx, s[i]);
        ans = max(ans, mx - mn);
        mn = min(mn, s[i]);
    }
    cout << ans << endl;
    return 0;
}
这份代码的时间复杂度是O(n)的,但该代码是错误的,我们有不知道错误出在什么地方,需要一组数据来辅助Debug。

对拍的具体过程如下:

  1. 在同一文件目录下创建3个cpp文件,其中a和b分别放入自己的代码与暴力代码:Windows C++程序对拍_第1张图片
  2. 另外建立三个文本文件,a.txt b.txt data.txt,其中,data.txt存放data.cpp生成的数据Windows C++程序对拍_第2张图片
  3. data.cpp中的代码如下:
#include 
using namespace std;

int main() {
    srand(time(0));
    int n = rand() % 5 + 1;
    cout << n << endl;
    for (int i = 1; i <= n; ++i) {
        int t = rand() % 10 - 5;
        cout << t << ' ';
    }
    return 0;
}

完全按照输入的格式生成随机数据,注意t - 5的目的是生成的数据中存在负数。n + 1的目的是保证n >= 1。对拍数据可以很小,你的目的是找到一组卡掉自己的数据,来辅助自己Debug,数据要有可读性。同时,生成的数据一定要有普遍性,即涵盖所有的特殊情况,只是范围可以小一点。比如本题中,生成的a数组不能只是正整数,而应该满足可正可负可为0,通常卡掉自己的数据正是一些特殊的情况。

  1. 编译,生成三者的exe可执行文件。Windows C++程序对拍_第3张图片
    由于我本地是使用的cygwin的g++环境,且已经配好了环境变量,可以直接使用终端来编译代码。也可以用其他方式来生成。
    将cmd命令行添加到右键菜单的方法(注意名称使用中文可能会导致乱码问题):https://blog.csdn.net/mooneve/article/details/78821843
    Windows C++程序对拍_第4张图片
  2. 正式开始对拍过程:
    在该目录下新建一个duipai.txt的文本文档 Windows C++程序对拍_第5张图片
    在其中添加如下代码:
color A 
echo off 
:loop
	echo run%a%
	set /a a+=1
	data.exe > data.txt
	a.exe < data.txt > a.txt
	b.exe < data.txt > b.txt
	fc a.txt b.txt
	if not errorlevel 1 goto loop
pause

代码解释,讲生成的数据存入data.txt,将a和b的程序运行结果放入a.txt和b.txt中,然后进行比对,注意ab两个程序的输出格式一定要相同,共同忽略行末空格或都不忽略。

  1. 将duipai.txt修改名称和类型为duipai.bat,然后就可以运行了。
    Windows C++程序对拍_第6张图片

几点补充:

  1. 如果本地采用的编译器是mingw,duipai.bat也可以改成cpp生成的exe文件。
    代码如下:
#include 
#include

using namespace std;

int main() {
    int t = 1;
    while (1) {
        system("data.exe>data.txt");
        system("a.exea.txt");
        system("b.exeb.txt");
        cout << "test " << t << ":" << endl;
        if (system("fc 1.txt 2.txt"))break;
        t++;
    }
    return 0;
}

Cygwin下不能正常使用Windows下的system命令,所以不能够这样用。

  1. 不能够正常使用文本文档流入流出的备用方案:
    直接将data.cpp a.cpp b.cpp改为重定向的文件输入输出,即用freopen打开文件,duipai文件中就不在添加"a.txt"或是">data.txt"这样的命令后缀,直接运行exe文件即可。

你可能感兴趣的:(算法竞赛专栏)