ACM对拍程序

以2019杭电多校的一道题为例。
题目传送门
将正确程序还有WA的程序放在同一目录下(这两个程序按照一般写法即可),然后再写个样例随机生成代码。然后代码都要编译一下,生成对应的exe文件,因为对拍程序调用的是exe文件,所以源代码改了,还要重新编译一下,更新exe文件。然后新建txt,写入一下代码。然后将文件后缀改为.bat,一切就绪后就可以双击.bat文件,windows会调用cmd窗口,显示运行结果。
如果文件不再同一目录,只要在文件前面加上盘符/等信息(绝对路径),自行谷歌。
对拍核心代码:

:again
test > input.txt
permutation1 < input.txt > test_output.txt
permutation2n < input.txt > rt_output.txt
fc /N test_output.txt rt_output.txt
if not errorlevel 1 goto again
pause

代码解释:
代码第一行类似于定义一个函数。
第二行,可以类比c++中的输入输出流,就是讲test.exe运行出来的结果写入input.txt文件,这就类似输出流。
第三行的<类似于输入流,也就是将input.txt文件的数据读入permutation程序中作为输入数据。
第四行,调用windows比较函数fc, /N是这个函数的参数。自己可以上网查阅。
其他的就没什么注意得了。
样例随机生成代码:

#include <iostream> 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <algorithm>
#include <windows.h>
using namespace std;
int fac(int x){
	int res = 1;
	for(int i = 2;i <= x;++i){
		res *= i;
		if(res > 1e4){
			return res;
		}
	}
	return res;
}
int main(){
	// freopen("food.in","w",stdout);
	// srand((unsigned)time(NULL));
	srand(time(0));
	int T = 0,n = 0,k = 0;
	int nT = 40,nn = 20,kk = 10000;
	T = rand() % nT + 1;
	printf("%d\n",T);
	while(T--){
		n = rand() % nn + 1;
		k = rand() % min(kk,fac(n)) + 1;
		printf("%d %d\n",n,k);
	}
	

	return 0;
}

AC代码:

#include<bits/stdc++.h>
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
using namespace std;
const int maxn = 20 + 10;
int n = 0,k = 0,cnt = 0;
int ans[maxn];
bool vis[maxn];
void init(){
	cnt = 0;
	per(i,1,n){
		vis[i] = false;
	}
}
bool dfs(int depth,int minv,int maxv){
	if(depth > n){
		++cnt;
		if(cnt == k){
			per(i,1,n){
				printf("%d%c",ans[i] - minv + 1,i == n ? '\n' : ' ');
			}
			return true;//如果找到了答案就停止dfs
		}
		return false;//否则继续寻找
	}
	per(i,maxv - (n-1),minv + (n-1)){
		if(vis[i]){
			continue;
		}
		ans[depth] = i;
		vis[i] = true;
		if(dfs(depth+1,min(minv,i),max(maxv,i))){
			vis[i] = false;
			return true;//如果找到了答案就停止dfs,退出循环,不在dfs该节点的其他子树
		}
		vis[i] = false;
	}
	return false;
}
int main(){
	int T = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&k);
		init();
		ans[1] = n;
		vis[ans[1]] = true;
		dfs(2,n,n);
	}
	return 0;
}

WA的代码:

#include<bits/stdc++.h>
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
using namespace std;
typedef long long LL;
#define INF 1e9
const int maxn = 30;
int n = 0,k = 0;
vector<int> ans;
bool vis[maxn];
int fac(int x){
	int res = 1;
	per(i,2,x){
		res *= i;
		if(res > 1e4){
			break;
		}
	}
	return res;
}
void init(){
	ans.clear();
	per(i,1,n){
		vis[i] = false;
	}
}
void solve(){
	int num = fac(n-1);
	ans.push_back(0);
	ans[0] = n+1 - ceil(k*1.0/num);
	vis[ans[0]] = true;
	if(k % num == 0){
		k = num;
	}else{
		k %= num;
	}
	rep(i,n-2,1){
		num = fac(i);
		int pos = ceil(k*1.0/num);
		int cnt = 0,las = -1;
		bool fg = true;
		per(i,1,n){
			if(!vis[i]){
				++cnt;
				las = i;
				if(cnt == pos){
					ans.push_back(i);
					fg = false;
					vis[i] = true;
					break;
				}
			}
		}
		if(fg){
			ans.push_back(las);
			vis[las] = true;
		}
		if(k % num == 0){
			k = num;
		}else{
			k %= num;
		}
	}
	per(i,1,n){
		if(!vis[i]){
			ans.push_back(i);
			break;
		}
	}
	per(i,0,n-1){
		printf("%d%c",ans[i],i == n-1 ? '\n' : ' ');
	}
	// printf("fnadsuiofhasofiaj\n");
}
int main(){
	// freopen("food.in","r",stdin);
	// freopen("food.out","w",stdout);
	int T = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&k);
		init();
		solve();
	}


	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章