信息學奧賽對拍寫法
-
現在基本上都是在linux下寫代碼,所以之給大家提供linux下的對拍版本。
-
以P1064 金明的預算方案為例,我們需要有一個根據題目要求的輸入數據生成代碼,我命名為 \(data.cpp\)。
-
下面的代碼實際上沒有嚴格按照題目要求做數據,但不影響對拍的結果。
-
\(data.cpp\)
#include <bits/stdc++.h> const int maxn=1e3; std::vector <int> a; int vis[maxn],zhu[maxn]; int main(){ srand(time(NULL));//隨機種子 int m=1000,n=rand()%10+1; printf("%d %d\n",m,n); for(int i=1;i<=n;++i){ int v=rand()%100+1,p=rand()%5+1; int q=rand()%n+1; while(q==i)q=rand()%n+1;//自己不能是自己的主件 if(vis[i]){//如果i是主件 printf("%d %d 0\n",10*v,p);continue; } if(zhu[q])q=zhu[q];//如果q有自己的主件,則讓i,q為兄弟 else{//如果q沒有自己的主件,那q就成為主件 vis[q]=1; } zhu[i]=q; printf("%d %d %d\n",10*v,p,q); } return 0; }
-
自己根據題意寫的代碼
-
\(my.cpp\)
#include <bits/stdc++.h> const int maxn=60+5,maxv=32000+5; struct Edge{ int to,next; }e[maxn]; int dp[maxn][maxv],a[maxn],p[maxn]; int head[maxn],len,n,m; void Insert(int u,int v){ e[++len].to=v;e[len].next=head[u];head[u]=len; } void Init(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int x;scanf("%d%d%d",&a[i],&p[i],&x);; Insert(x,i); } } void dfs(int u,int fa){ for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==fa)continue; dfs(v,u); for(int j=n-a[u];j>=a[v];--j) for(int k=0;k<=j;++k) dp[u][j]=std::max(dp[u][j],dp[u][j-k]+dp[v][k]); } if(u==0)return; for(int i=n;i>=0;--i){ if(i>=a[u]) dp[u][i]=dp[u][i-a[u]]+a[u]*p[u]; else dp[u][i]=0; } } void Solve(){ Init(); dfs(0,-1); printf("%d\n",dp[0][n]); } int main(){ Solve(); return 0; }
-
保證正確,但時間效率並一定高的代碼,要求好寫,准確,下面代碼隨便在網上找了份
-
\(force.cpp\)
#include <iostream> #define maxn 32005 using namespace std; int n,m; int v,p,q; int main_item_w[maxn]; int main_item_c[maxn]; int annex_item_w[maxn][3]; int annex_item_c[maxn][3]; int f[maxn]; int main(){ cin >> n >> m; for (int i=1;i<=m;i++){ cin >> v >> p >> q; if (!q){ main_item_w[i] = v; main_item_c[i] = v * p; } else{ annex_item_w[q][0]++; annex_item_w[q][annex_item_w[q][0]] = v; annex_item_c[q][annex_item_w[q][0]] = v * p; } } for (int i=1;i<=m;i++) for (int j=n;main_item_w[i]!=0 && j>=main_item_w[i];j--){ f[j] = max(f[j],f[j-main_item_w[i]]+main_item_c[i]); if (j >= main_item_w[i] + annex_item_w[i][1]) f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] ] + main_item_c[i] + annex_item_c[i][1]); if (j >= main_item_w[i] + annex_item_w[i][2]) f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][2]); if (j >= main_item_w[i] + annex_item_w[i][1] + annex_item_w[i][2]) f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][1] + annex_item_c[i][2]); } cout << f[n] << endl; return 0; }
有了上面的三份代碼,並把三個程序編譯生成的三個可執行程序\(data,my,force\) 放在同一個目錄下即可一用下面的兩種方法進行對拍
- c++版本
#include <bits/stdc++.h>
int main(){
int i=0;
while(1){
++i;
system("./data > data.in");//把data.cpp輸出數據寫到data.in
system("./my < data.in > my.out");//my.cpp從data.in讀取數據,結果輸出到my.out
system("./force < data.in > force.out");//force.cpp從data.in讀入數據,結果寫到force.out
if(system("diff my.out force.out"))//比較兩個輸出是否相同
break;//不相同就跳出
else
printf("%d AC\n",i);
}
return 0;
}
- \(shell\) 版本
#! /bin/bash
while true;do
./data > data.in #生成的數據寫入到文件data.in
./my < data.in > my.out # my從data.in讀人數據,結果輸出到my.out
./force < data.in > force.out #force從data.in讀入數據,結果寫入到force.out
if diff my.out force.out;then # 比較兩個文件內容是否完全一樣
printf "ac\n"
else
printf "wa\n"
exit 0
fi
done