C++对拍

版权声明:本文为博主原创文章,不管你喜不喜欢都请在注明作者后转载~( ̄▽ ̄~) https://blog.csdn.net/C20190102/article/details/82944384

前言

近期考古发现,本人于2017年3月水了一篇对拍
我发现它实在是水,估计没多少人看得懂。
作为一个内心善良,乐于助人,无比有爱心的人。

我决定再水一篇对拍。


本文废话较多,代码较恶心,诸君可以跳跃性阅读。


对拍

解释

根据百度汉语对“拍”的解释,好像无法理解这个词。
简单来说,就是写一个数据生成器,然后把生成的数据给两个不同的程序运行,比较它们输出的结果。
主要有两个用途:

  • 比赛(考试)时,写了一个自以为正确的程序,但是还是不放心,可以再写一个暴力程序,对拍验证。
  • 做题做到天昏地暗,头晕目眩,不分东南西北之时,眼前一片血红,于是不小心偷了一个充满生命力的代码,再写个数据生成器,说不定对拍能挽救代码的生命。

例题

A+B Problem

数据生成器

方法

生成随机数之必备武器:ctimecstdlib
main开头写:

srand((unsigned)time(NULL));

意思大概是设置随机数的种子为你的时间。
如果你不写或者写个srand(1234567),你发现你每次生成的“随机数”都是一样的。

然后使用:

int x=rand();

就可以得到一个 0 0 到不知道多少(RAND_MAX)的整数。
如果你想得到得到 [ a , b ] [a,b] 之间的一个整数:

int x=rand()%(b-a+1)+a;

如果 a , b a,b 有些大,可以这样,以防数据太弱:

int x=1ll*rand()*rand()%(b-a+1)+a;

如果想得到浮点数,除以 10 10 即可。

当然,如果想要生成一个树、一个连通图、一个二分图什么的,加点数据结构之类的就行了
曾经我为了对拍一个破圈法的题,写了100多行的数据生成器。

代码

#include<ctime>
#include<cstdio>
#include<cstdlib>

#define MAXN 1000

int main(){
    srand((unsigned)time(NULL));
    int A,B;
    A=rand()%MAXN;
    B=rand()%MAXN;
    printf("%d %d\n",A,B);
    //想像一下用手输数据的时候不打换行会怎么样,这里就会怎么样
}

你的程序 == WA

什么都不用加,找的你的程序的exe文件即可。

#include<cstdio>

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d",a/b*b+b);
}

我的程序 == AC

什么都不用加,偷到我的程序的exe文件即可。
没有时间了,只好先水一个SPFA,如有错请见谅 。

#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;

#define MAXM 2
#define MAXN 3
struct Edge{
    int v,w;
    Edge *Next;
}E[MAXM+5];
Edge *ecnt,*First[MAXN+5];

void Init(){
    ecnt=&E[0];
    memset(First,0,sizeof First);
}

void AddEdge(int u,int v,int w){
    ++ecnt;
    ecnt->v=v,ecnt->w=w;
    ecnt->Next=First[u],First[u]=ecnt;
}

int dist[MAXN+5];
bool vis[MAXN+5];
int SPFA(int S,int T){
    memset(vis,0,sizeof vis);
    memset(dist,0x3f,sizeof dist);
    queue<int> Q;Q.push(S);
    dist[S]=0,vis[S]=1;
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();vis[u]=0;
        for(Edge *i=First[u];i!=NULL;i=i->Next){
            int v=i->v,w=i->w;
            if(dist[v]>dist[u]+w){
                dist[v]=dist[u]+w;
                if(!vis[v]){
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    return dist[T]==0x3f3f3f3f?-1:dist[T];
}

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    Init();
    AddEdge(1,2,a);
    AddEdge(2,3,b);
    printf("%d",SPFA(1,3));
}

AC证明:
AC证明

对拍程序

其实我的续集只是续的这个部分。
古文《对拍》中,是使用的C++写对拍,各位是不是感觉很慢?看上去很不爽?还要编译?
所以现在使用bat文件完成对拍,Windows下有一个命令:fc,可以比较两个文件。

准备活动

方法:

  • 在一个你喜欢的位置新建一个记事本文件dp.txt
  • 将后缀.txt改成.bat,所以你的文件变成了dp.bat

这个时候问题来了:
我的文件是这样的嘤嘤嘤:
没有后缀的情况
这样做:
随意打开一个文件夹 \to (左上角)组织 \to 文件夹和搜索选项 \to (上方)查看 \to 下面的高级设置中找到“隐藏已知文件类型的扩展名”,把前面的勾去掉即可。
显示扩展名的方法(1)

显示扩展名的方法(2)
然后你就会发现变成了这样:
扩展名出现了
.txt改成.bat
扩展名为bat


代码

继续:

  • 右键dp.bat,点击“编辑”

接下来才是重点。
仔细观察你即将粘贴进去的代码:

@echo off
:loop
	数据生成器位置 > data.txt
	你的程序的位置 < data.txt > yours.txt
	我的程序的位置 < data.txt > mine.txt
	fc yours.txt mine.txt
	if not errorlevel 1 goto loop
pause
goto loop

你急用就直接粘过去,如果你希望考试的时候能用就继续看。

示例

@echo off
:loop
	C:\3\bin\Debug\3.exe > data.txt
	C:\1\bin\Debug\1.exe < data.txt > yours.txt
	C:\2\bin\Debug\2.exe < data.txt > mine.txt
	fc yours.txt mine.txt
	if not errorlevel 1 goto loop
pause
goto loop

注意一定要填exe文件。
4个文件的示例
把上面的代码保存后,直接双击dp.bat
一次对拍
你一定看懂了它的意思。
这时打开data.txt,里面是你的数据生成器生成的数据,yours.txtmine.txt分别是你的输出结果和我的输出结果。

当然,你可以“按任意键继续”。
如果输出一样是什么效果请自行试验。

更多内容

这里个人是对对拍代码的解读,更准确的内容请百度。

  • @echo off:此句可不要,但会多输出一些提示性语句。echo有回声的意思,应该是指回显,而off就是关闭。至于为什么fc的回显没有关闭,不知道= =
  • :loopgoto loop:等于C++loop:goto loop,相当于循环。
  • <>:大概是运行后输入输出之意。
  • fc FILE1 FILE2:比较FILE1FILE2
  • if not errorlevel 1:大概是看fc的“返回值”,判断两文件是否相同。
  • pause:按任意键继续

以上语句全部可以通过C++system函数运行,效果相同。

后记

感谢你阅读到了这里(可能你是一下子拉到底的),本文确实废话较多,但是之前的《对拍》有些内容确实不太优秀,我又不忍心删掉它,所以写了这样一篇。

猜你喜欢

转载自blog.csdn.net/C20190102/article/details/82944384