由于时间不足,本人在新生赛仅浏览了四题,其中两题完全通过。
下面是已解出的一题,供比对和取优。
下面贴上原题:
我的思路: 首先需要一个while(scanf)循环,以供测试器循环测试各组数据。然后因为需要输入T组数据,所以还需要一个if循环或者while循环。数据的输入也需要利用到到数组,比如a[i]。再者,输出时需要判断是第几次输出,输出一个可自增的量(%d,c++)。最后,需要一个判断if以决定输出嘤嘤嘤还是苦海无涯。
贴上我的代码,我们把它叫做代码a:
#include
int main(){
int a,b=0,c,d,i;
while(scanf("%d",&a) !=EOF){
while(a--){
int g=0;
b++;
scanf("%d",&c);
int d[c+1];
for(i=1;i<=c;i++){
scanf("%d",&d[i]);
}
int f=0;
while(c--){
f++;
if(d[d[d[f]]]==f){
printf("Case #%d: 苦海无涯\n",b);
g=1;
break;
}
}
if(g==0){
printf("Case #%d: 嘤嘤嘤\n",b);
}
}
}
return 0;
}
出题者提供的代码,我们把它叫做代码b:
#include
int main() {
int T, n;
int a[5005];
scanf("%d", &T);
int cas = 1;
while(T--) {
scanf("%d", &n);
int flag = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++) {
if(a[a[a[i]]] == i){
flag = 1;
break;
}
}
if(flag){
printf("Case #%d: 苦海无涯\n",cas++);
}else {
printf("Case #%d: 嘤嘤嘤\n",cas++);
}
}
return 0;
}
在这里对比一下两段代码,以及写一下他们所用到的知识。
代码a:
while(scanf("%d",&a) !=EOF){ //输入一个数字,决定总程序要循环多少次
while(a--){ //while(0)为结束
int g=0;
b++; //b代表是第几次循环,决定输出case几
scanf("%d",&c); //输入一个数字代表人数
int d[c+1]; //定义数组,输入数字的值决定了要定义多少个数组
for(i = 1; i <= c; i++)
scanf("%d",&d[i]); //循环给数组赋值,直到结束
}
}
代码b:
int a[5005]; //直接定义5005个数组
scanf("%d", &T);
while(T--) { //同样循环T次
scanf("%d", &n);
int flag = 0;
for(int i = 1; i <= n; i++) { //循环赋值
scanf("%d", &a[i]);
}
这两段代码的区别在于a代码没有直接定义数组的个数,b直接定义了有5005个数字,根据题目来看,其实两种方法都可以。
while(0)代表while(false)程序将不执行,当while里面的值仍然是非零数的时候,程序会继续循环。
代码a:
int f=0; //每次循环先将f定义为0,以方便后面判断
while(c--){
f++; //每次循环自增,判断各人是否符合条件
if(d[d[d[f]]]==f){
printf("Case #%d: 苦海无涯\n",b);
g=1; //g=1是为了跳过下方嘤嘤嘤的判断
break; //跳出语句,不必要重复执行,减少运行时间
}
}
if(g==0) //如果不曾有过进入上方的if,则会输出嘤嘤嘤
printf("Case #%d: 嘤嘤嘤\n",b);
代码b:
int cas = 1;
for(int i = 1; i <= n; i++) {
if(a[a[a[i]]] == i){
flag = 1;
break;
}
}
if(flag){ //if(flag),flag为真时,也就是等于1时进入苦海无涯
printf("Case #%d: 苦海无涯\n",cas++); //cas自增,由于两种情况都会输出cas,所以没有问题
}else {
printf("Case #%d: 嘤嘤嘤\n",cas++);
}
}
在这里讲一下,为什么是a[a[a[i]]] == i呢
我们假设有一个数组是:
1 | 2 | 3 | 4 |
---|---|---|---|
3 | 1 | 2 | 2 |
在这个数组里面,很明显是有三角恋的,因为1喜欢3,3喜欢2,2喜欢1。
我们把数组看成是一种函数:
x | 1 | 2 | 3 |
---|---|---|---|
f(x) | 3 | 1 | 2 |
那么这个表格就可以变成:
x | 1 | f(f(1)) | f(1) |
---|---|---|---|
f(x) | f(1) | f(f(f(1))) | f(f(1)) |
那么问题就变成了f(f(f(1)))是不是等于1的问题了,同样可以推理出可以变成f(f(f(x)))是不是等于x的问题。
代码部分分为两种方式,个人认为第二种方法更好。代码b减少了嵌套,将函数功能模块化,便于维护与理解。同时,有良好的代码习惯作为基础,这些都是我需要学习的。目前来看,我应该在代码的整洁性以及规范性上面下一些功夫。
出题者代码摘自:https://blog.csdn.net/anthony1314/article/details/82926950
感谢bnuz-acm协会为我们举行的国庆欢乐赛,感谢参与了欢乐赛的老师及同学们,希望acm协会能越办越好。