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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章