OI造数据以及Lemon评测教程

OI造数据以及Lemon评测教程

前言

所谓数据,就是我们对解决某个问题的程序正确与否进行判断的依据。

不同的题目会考虑到时间和空间复杂度,所以需要对数据有严格要求,甚至部分数据只能人为创造。

本教程是基于C/C++和Python的造数据教程,如果不会,请先继续向后看,之后再去学习对应的知识点即可。

并且在后文提供了软件Dev-C++ & Thonny(python集成ide) & Lemon(数据评测软件)的下载地址,Lemon教程在下载处就有,本文在后续会考虑再次更新。

案例一:A+B

最快入门的方式就是做一次题。所以这里会演示一个造数据的全部过程,各位看官请落座。

例:输入两个整数 a,b,输出它们的和,已知 0< a, b<1e+3。

输入样例:1 2   输出样例:3

在造数据前我们需要解决这个问题,得到该问题的标程(标准程序),并命名 std.cpp

#include
#include
using namespace std;

int main(){
	int a,b;  cin>>a>>b;
	cout<<a+b<<endl;	
	return 0; 
} 

那么接下来就开始造数据之旅了,我们需要对标程进行细微的调整,主要是main函数传入参数,开启文件重定向,调整后如下。

#include
#include
using namespace std;

int main(int argc,char **argv){
	freopen(argv[1],"r",stdin); // agv[1]这样书写是用于造数剧,如果用于评测这是不对的
	freopen(argv[2],"w",stdout);
	
	int a,b;  cin>>a>>b;
	cout<<a+b<<endl;	
	return 0; 
} 

对于main函数中参数的解释,命名 t1.cpp

#include
#include
using namespace std;

/*	argc 命令行参数总数
 	argv 命令行参数的字符串指针
	argv[0]  程序名
	argv[1+] 用户输入的参数 
	所以有人也写成 int main(int argc,char *argv[]){}*/ 
int main(int argc,char **argv){
	for(int i=0; i<argc; i++){
		cout<<argv[i]<<" ";
	} 
	return 0; 
} 

上述程序 t1.cpp 运行效果:

Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\Users\Administrator\Desktop\造数据>g++ t1.cpp -o t1

C:\Users\Administrator\Desktop\造数据>t1.exe 1 2 3 4 5
t1.exe 1 2 3 4 5             

C:\Users\Administrator\Desktop\造数据>

接下来我们就要开始使用Python造数据了,准备好了吗!

关于dos命令演示如下,当我们建立一个1.in文件,并存入数字{ 1 2 },运行该命令就会生成1.out,并向里面存入std.exe执行输入1.in中数据的结果{ 3 }。

Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\Users\Administrator\Desktop\造数据>g++ t1.cpp -o t1

C:\Users\Administrator\Desktop\造数据>t1.exe 1 2 3 4 5
t1.exe 1 2 3 4 5
C:\Users\Administrator\Desktop\造数据>std.exe 1.in 1.out                       

C:\Users\Administrator\Desktop\造数据>

但是这样运行哪有一键Python来的快呢!且看如何使用Python快速进行数据的生成!

C++ 代码,命名 std.cpp -->执行生成 std.exe ,与python最后一行代码对应
import os
import random

# 说明:ans=a+b, 0<=a,b<=1000
for i in range(1,11): # [1,11) 以步长为1进行递增
    with open("%d.in" %i, "w") as fout: # 新建文件i.in
        a = random.randint(0, 1000) # 生成随机整数,该数范围 [0,1000]
        b = random.randint(0, 1000) # 生成随机整数,该数范围 [0,1000]
        fout.write("%d %d" %(a,b))  # 将a b写入文件i.in
    os.system(r".\std.exe %d.in %d.out" %(i,i)) # dos命令, 注意std.exe,不一定一样,但一定要对应标程

案例一:A+B总结

上述的练习,我们了解了基本过程和原理,接下来做个步骤汇总:

  1. 建立C/C++标程(命名 std.cpp),并将main函数修改为有参函数,增加文件重定向,并运行生成 .exe 文件

  2. 建立Python脚本(命名 std.py),注意参数对应,数据量

对于源码的命名其实没有这样的要求,只要程序关键对应即可,这只是让初学者有这样一种格式化的认识罢了!
std.cpp

#include
#include
using namespace std;

int main(int argc,char **argv){
	freopen(argv[1],"r",stdin); 
	freopen(argv[2],"w",stdout);
	
	int a,b;  cin>>a>>b;
	cout<<a+b<<endl;	
	return 0; 
} 

std.py

import os
import random

# 说明:ans=a+b, 0<=a,b<=1000
for i in range(1,11): # [1,11) 以步长为1进行递增
    with open("%d.in" %i, "w") as fout: # 新建文件i.in
        a = random.randint(0, 1000) # 生成随机整数,该数范围 [0,1000]
        b = random.randint(0, 1000) # 生成随机整数,该数范围 [0,1000]
        fout.write("%d %d" %(a,b))  # 将a b写入文件i.in
    os.system(r".\std.exe %d.in %d.out" %(i,i)) # dos命令, 注意std.exe要对应标程

案例二:P1090 [NOIP2004 提高组] 合并果子

题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n−1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 1 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有 3 种果子,数目依次为 1 , 2, 9 。可以先将 1 、 2 堆合并,新堆数目为 3 ,耗费体力为 3 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12 ,耗费体力为 12 。所以多多总共耗费体力 =3+12=15。可以证明 15为最小的体力耗费值。

输入格式

共两行。

第一行是一个整数 n ( 1 ≤ n ≤ 10000 ) (1\leq n\leq 10000) (1n10000),表示果子的种类数。

第二行包含 n个整数,用空格分隔,第 i 个整数 a i ( 1 ≤ a i ≤ 20000 ) a_i(1\leq a_i\leq 20000) ai(1ai20000)是第 i 种果子的数目。

输出格式
一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2 31 2^{31} 231

输入输出样例
输入 #1

3 
1 2 9 

输出 #1

15

说明/提示

对于30%的数据,保证有 n ≤ 1000 n \le 1000 n1000;

对于50%的数据,保证有 n ≤ 5000 n \le 5000 n5000

对于全部的数据,保证有 n ≤ 10000 n \le 10000 n10000

开始造数据吧!

第一步:出标程

#include
#include
using namespace std;

int main(int argc, char**argv){
    freopen(argv[1], "r", stdin);
    freopen(argv[2], "w", stdout);
	
	int n,a,ans=0;cin>>n;
	priority_queue<int, vector<int>, greater<int> >q;//升序排序,小顶堆 
	//priority_queue ,less >q;  //降序排列,大顶堆 

	for(int i=1; i<=n; i++){
		cin>>a;
		q.push(a);
	}
	for(int i=1; i<n; i++){
		a = q.top();//访问队头元素 
		q.pop();	//弹出队头元素 
		a += q.top(); 
		q.pop();
		ans += a;
		q.push(a);	//插入元素到队尾,并排序 
	}
	cout<<ans;
	return 0;
}

第二步:出脚本,注意数据要求范围

import os
import random

for i in range(1,11):
    with open("%d.in" %i, "w") as fout:
        if i<=3:
            n = random.randint(1, 1000)
        elif i<=5:
            n = random.randint(1, 5000)
        else:
            n = random.randint(1, 10000)
        fout.write("%d\n" %n)
        
        for j in range(1, n+1):
            ai = random.randint(1,20000)
            fout.write("%d " %ai)
    os.system(r".\std.exe %d.in %d.out" %(i,i))

使用lemon评测

lemon的使用,在以下提供的网址中有明确讲解,这里就不多赘述了。

软件下载

Dev-C++:https://pc.qq.com/detail/16/detail_163136.html

Thonny & Python :http://www.downza.cn/soft/277053.html

Lemon:http://www.pc6.com/softview/SoftView_630536.html

参考资料

【使用python生成信息学奥赛题目测试数据】

【C++造数据 和 对拍】

你可能感兴趣的:(C++,c++,c语言)