在比赛中我们常常会遇到这样的输入格式:给出一个n行m列01矩阵,且这个矩阵相邻元素间无空格。
比如说这样的:
3 3
101
011
110
这时候就无法用%d读入了……
而我们知道c++有一种冷门的读入方法 scanf(“%1d”,&x) 。
为了方便,我曾多次这样读01矩阵,结果这次模拟赛的某一题,由于%1d的效率问题,我从100分TLE到了61…Orz
然后我惊讶的发现某度上并无关于%1d的读入效率说明(可能是太冷门了吧),所以我测试了一下%1d的效率。
用%1d读入的代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
scanf("%1d",&x);
}
}
return 0;
}
用%c读char再强转int的代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
char y=' ';
while(y!='0'&&y!='1')scanf("%c",&y);
x=y-'0';
}
}
return 0;
}
原始的数据生成器
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
freopen("test.in","w",stdout);
scanf("%d%d",&n,&m);
printf("%d %d\n",n,m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d",rand()&1);
}
printf("\n");
}
return 0;
}
结果如下:
数据范围 | %1d | %c |
---|---|---|
n=m=100 | 0.21s | 0.16s |
n=m=500 | 0.27s | 0.20s |
n=m=1000 | 0.54s | 0.31s |
n=m=2000 | 1.64s | 0.71s |
n=m=5000 | 9.16s | 3.40s |
嗯更大的数据我家老爷机的rand()短时间内跑不出来了,测不了…
这也证明了rand()的效率是多么的低…STO
可以看出当数据范围很大时,%1d的读入要比读入字符慢很多倍,这种效率是竞赛中难以承受的,所以还是要尽量避免使用%1d,虽然一个个读字符会让程序变得很丑。