卡时
卡时
背景
有的时候,我们的搜索会搜很很很很很久,会\(TLE\)。\(TLE\)的分数\(=0\),但是如果你在即将\(TLE\)时输出了当前最优解,分数即可\(\geqslant 0\)。那么这是就需要卡时。
什么是卡时
卡时,顾名思义,卡时间,就是我们要用一个东西记录当前的时间,如果快要超时了,输出当前最优解,结束。
实现
朴素版(错误
#include<bits/stdc++.h>
//#include<ctime>
//如果你不用bits/stdc++.h那么一定要加ctime
using namespace std;
int st;
signed main(){
st = clock();//记录一下当前的时间的
while(1){//假装在搜索
if(clock()-st >= 0.95) break;
//如果现在时间-开始时间要超过1s了,退出
}
cout << 52520 << endl;//输出当前搜索出的最优解
return 0;
}
这时,如果你交到洛谷上,你会惊奇的发现,你的每个测试点都在\(1ms\)以内结束了,这是因为洛谷是\(Linux\)系统,算时间是单位用的微秒,\(0.95\)代表的\(0.95μs\),也就是不到\(1ms\),那么你也不知道你叫的评测机是什么单位的,这时就要统一单位。
朴素版
我们只要一个东西,CLOCK_PEP_SEC
,这个用来存当前系统\(1s\)内时间单位的个数,它就是\(1s\),再乘个\(0.95\)即\(950ms\)。
#include<bits/stdc++.h>
using namespace std;
int st;
signed main(){
st = clock();//记录一下当前的时间的
while(1){//假装在搜索
if(clock()-st >= 0.95*CLOCK_PEP_SEC) break;
//如果现在时间-开始时间要超过1s了,退出
//CLOCK_PEP_SEC是1s时间单位的个数
}
cout << 52520 << endl;//输出当前搜索出的最优解
return 0;
}
优化版
我们又发现这里有一个实数乘法,众所周知……
如果我们说加法的时间是\(1\),那么减法也是\(1\),乘法呢?
\(100\)
没有那么多,也就\(32\)。
除法呢?
\(100\)
没有那么多,也就\(1000\)吧。
这里虽然是乘法,但是是实数,我们想让它成为整数乘法,怎么弄?两边同乘以\(1000\)即可。
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
int st;
signed main(){
st = clock();//记录一下当前的时间的
while(1){//假装在搜索
if((clock()-st)*1000 >= 950*CLOCK_PEP_SEC) break;
}
cout << 52520 << endl;//输出当前搜索出的最优解
return 0;
}
最终\(dfs\)版
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
int st;
void dfs(){
if(clock()-st*1000 >= 950*CLOCK_PEP_SEC){
cout << 52520 << endl;//输出当前最优解
exit(0);//退出整个程序,约等于return 0;
}
dfs();
}
signed main(){
st = clock();//记录一下当前的时间的
dfs();
return 0;
}
卡多久
\(999\)吗?不行。首先后面还要输出最优解和退出程序,时间不够的退出。其次,评测机波动会导致时间变化。(比如今天一个同学相同代码第一次交\(80\),第二次交直接\(100\)
那就\(950\)吧。其实可以,但是\(CCF\)重测时时限超过\(950ms\)就不给重测了(虽然没有人会去重测,据老师所知,重测没有成功的)。
所以综上所述,大概\(900\)就可以了