对拍是算法竞赛中一个很重要的技巧,当某个问题,你用高深的算法写写的里心里发慌,而使用最简单的暴力可以轻轻松松写过的时候,对拍,就发挥了其价值,可以检查你的代码究竟写的对不对。
那么我们应该如何进行对拍呢?以LINUX系统为例,首先,我们需要掌握三份代码,第一份,那就是你要对拍的程序,就是你要用来检查是否正确的程序,第二份,标准程序,标准程序可以是你写的暴力解法程序,亦可以是某个大佬写的程序,总而言之,一定要保证正确,第三份,随机数生成器,随机数生成工具一定要与前两份的输入输出相匹配,这样才能保证正确的对拍。
在准备完如上三个程序后,我们使用一个脚本来进行对拍,在实行对拍前,请将对拍脚本,和那三个程序放在同一个文件夹内。对拍脚本如下。
`
#!/bin/bash
#author:liuliu
read -p "请输入你需要对拍的程序" todobe
read -p "请输入标准程序,确保正确" std
read -p "请输入data数据集合,确保正确" data
echo "需要对拍的程序是$todobe,标准程序是$std,随机数生成工具是$data"
printf "读入成功,现在进入编译阶段\n"
g++ $todobe.cpp -o $todobe
g++ $std.cpp -o $std
g++ $data.cpp -o $data
printf "生成成功,下面进入对拍\n"
while true; do
./$data > $data.in
./$std $std.out
./$todobe $todobe.out
if diff $std.out $todobe.out; then
printf "过"
else
printf "哇"
fi
done
`
执行如上对拍脚本,使用chmod +x (脚本名字) 然后执行./*.sh,或者干脆直接sh ./脚本名 字
然后比对结果,如上面,过就是过,没过就是哇。
上面的read是shell中专门用来读取输入的,剩下的都是管道符等乱七八糟的,都是linux shell编程中的知识,网上有相关的资料,这里不在另行解释。
补充:上面的g++自动编译,免去手动编译的烦恼。
对拍案例:
计算数组的和
输入:
第一行为数组内数字个数n
第二行为数组内数字,总共n个。
输出:
数组各个元素和
样例输入
5
1 2 3 4 5
样例输出:
15
对拍标准程序如下:
#include
using namespace std;
int main()
{
int i;
cin >> i;
int num[i];
for(int t=0;t
{
cin >> num[t];
}
int sumx = 0;
for(int t=0;t
{
sumx = sumx + num[t];
}
cout << sumx << endl;
return 0;
}
你要检验的代码如下:
#include
using namespace std;
int main()
{
int i;
cin >> i;
int num[i];
for(int t=0;t
{
cin >> num[t];
}
int sumx = 0;
for(int t=0;t
{
sumx = sumx + num[t];
}
cout << sumx << endl;
return 0;
}
下面重要的一环来了,随机数生成器
#include
using namespace std;
int main()
{
srand(time(0));
int i = rand()%10+1;
cout << i <
while(i--)
{
cout << rand()%10+1 << endl; //匹配第二行输出
}
}
然后运行脚本:
输入你要对拍的文件名,标准程序文件名,数据生成器
(不需要加后缀名,详情看对拍脚本的shell代码)
结果如下:
看到那上面的过了么,我们程序写成功,对拍也写成功了,下面,同样的程序,我们把对拍的标准程序改一下。程序要求算加,某个蒟蒻算成了积。
结果会怎么样呢?
WA掉了。
用好对拍,以后可以在cf叉叉人,可以检验自己写的对不对,还能学习linux脚本编程,何乐而不为呢?