来源:http://www.patest.cn/contests/pat-b-practise/1001
重点:循环条件控制,很容易出细微的逻辑错误。
#include<stdio.h>
int main() {
int n = 0, hold = 0, i = 0, j = 0, k = 0, times = 0;
int arr[105] = {0};
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &hold);
arr[i] = hold;
}
for (i = 0; i < n; i++) { //遍历arr中每一个数
j = arr[i];
times = 0; // times是为了防止某个数覆盖的数太多,而后面一些所覆盖的数大于100的很多是无意义的。后面有说明。
if (j == 0) continue;// 为0,说明已被覆盖,直接跳过。
do { // 此个do-while循环是最多遍历50个没被覆盖的数所能覆盖的数,用times控制
times++;
if ((j&1) == 0)
j >>= 1;
else
j = (3*j + 1)/2;
for (k = 0; k < n; k++) {// 若arr中的某个数被覆盖了,令它为0
if (arr[k] == j) {
arr[k] = 0;
}
}
} while ((times < 50 ) || (j < 1000 && j > 1));//当times超过49,或者j已经归1.跳出。由对arr[i]操作过到对arr[i+1]操作.!!!这里很重要,我之前debug了好久才发现是这里条件错了!!!!
}
for (i = 0; i < n - 1; i++) { //排序,为使结果降序输出
for (j = n - 1; j > i; j--) {
if (arr[j] > arr[j-1]) {
hold = arr[j];
arr[j] = arr[j-1];
arr[j-1] = hold;
}
}
}
for (i = 0; i < n; i++) {// 按要求输出未被覆盖,即不为0的数。
if (arr[i] != 0 && arr[i+1] != 0) {
printf("%d ", arr[i]);
} else if (arr[i] != 0 && arr[i+1] == 0){
printf("%d", arr[i]);
break;
}
}
return 0;
}
对times控制的说明:
//从2到100便利,找出这堆数所覆盖值的最大值,和每个数最多需要对j处理的次数的最大值
#include<stdio.h>
int main() {
int j = 0 ,i = 0;
long max = 0,times = 0,times_max = 0, max_max = 0;
for (i = 2; i <= 100; i++) {
max = 0;
times = 0;
j = i;
do {
if ((j&1) == 0) {
j >>= 1;
} else {
j = (3*j + 1)/2;
}
times++;
if (j > max)
max = j;
} while (j > 1);
if (times > times_max)
times_max = times;
if (max > max_max)
max_max = max;
}
printf("max:%ld\n", max_max);
printf("times:%ld\n", times_max);
return 0;
}
运行结果出乎意料。
这说明:原来我的times是不必要的。但是懒惰的博主不想删了。聪明的读者可以自行改良。