一.
P1059 [NOIP2006 普及组] 明明的随机数
题目描述
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
输入格式
输入有两行,第1行为1个正整数,表示所生成的随机数的个数N
第2行有N个用空格隔开的正整数,为所产生的随机数。
输出格式
输出也是两行,第1行为1个正整数MM,表示不相同的随机数的个数。
第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a[1001]={0};
int i,t,cent=0;
for(i=0;i<n;i++)
{
scanf("%d",&t);
a[t]++;
}
for(i=0;i<1001;i++)
{
if(a[i]!=0)
{
cent++;
}
}
printf("%d\n",cent);
for(i=0;i<1001;i++)
{
if(a[i]!=0)
{
printf("%d ",i);
}
}
return 0;
}
一道比较基础的题目,用了桶排序解决去重和排序的问题,但是最后输出时一开始输出的是a[i],即把出现次数输了出来,这里应该改为i,使随机数被输出,这个小问题在本次做题时多道题目都有体现,以后类似情况需要多注意.
二.
P1152 欢乐的跳
题目描述
一个n个元素的整数数组,如果数组两个连续元素之间差的绝对值包括了[1,n-1]之间的所有整数,则称之符合“欢乐的跳”,如数组1423符合“欢乐的跳”,因为差的绝对值分别为:3,2,1。
给定一个数组,你的任务是判断该数组是否符合“欢乐的跳”。
输入格式
每组测试数据第一行以一个整数n(1≤n≤1000)开始,接下来n个空格隔开的在[-10^8,10^8]之间的整数。
输出格式
对于每组测试数据,输出一行若该数组符合“欢乐的跳”则输出"Jolly",否则输出"Not jolly"。
#include <stdio.h>
#include <math.h>
int main()
{
int n;
scanf("%d",&n);
int i,j,s,flag=0;
long long a[100000];
int b[100000];
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
for(i=1;i<=n-1;i++)
{
b[i]=0;
}
for(i=0;i<n-1;i++)
{
j=i+1;
s=a[i]-a[j];
s=abs(s);
b[s]=1;
}
for(i=1;i<n-1;i++)
{
if(b[i]==0)
{
flag=1;
break;
}
}
if(flag==0)
printf("Jolly");
if(flag==1)
printf("Not jolly");
return 0;
}
之前一直没有找到WA的问题究竟在哪里,因为只注意到了题目中的条件(1≤n≤1000)而没有注意到"n个空格隔开的在[-10^8,10^8]之间的整数"这个条件,从而没有根据值域去创建b数组,导致数组过小,调整数组大小后即可通过
三.
P5143 攀爬者
题目背景
HKE考完GDOI之后跟他的神犇小伙伴们一起去爬山。
题目描述
他在地形图上标记了N个点,每个点Pi都有一个坐标(xi,yi,zi)。所有点对中,高度值z不会相等。HKE准备从最低的点爬到最高的点,他的攀爬满足以下条件:
(1) 经过他标记的每一个点;
(2) 从第二个点开始,他经过的每一个点高度z都比上一个点高;
(3) HKE会飞,他从一个点Pi爬到Pj的距离为两个点的欧几里得距离。即,sqrt{(Xi-Xj)^2+(Yi-Yj)^2+(Zi-Zj)^2}
现在,HKE希望你能求出他攀爬的总距离。
输入格式
第一行,一个整数N表示地图上的点数。
接下来N行,三个整数xi,yi,zi表示第i个点的坐标。
输出格式
一个实数,表示HKE需要攀爬的总距离(保留三位小数)
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
struct dis
{
double x;
double y;
double z;
};
struct dis a[50002],temp;
void quicksort(int left,int right)
{
double t=a[left].z;
int i=left;
int j=right;
if(left>right)
return ;
while(i!=j)
{
while (a[j].z>=t&&j>i)
j--;
while(a[i].z<=t&&i<j)
i++;
if(i!=j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
temp=a[i];
a[i]=a[left];
a[left]=temp;
quicksort(left,i-1);
quicksort(i+1,right);
}
int main()
{
int n;
scanf("%d",&n);
int i;
for(i=0;i<n;i++)
{
scanf("%lf %lf %lf",&a[i].x,&a[i].y,&a[i].z);
}
quicksort(0,n-1);
double d;
d=0;
for(i=0;i<n-1;i++)
{
d+=sqrt((a[i+1].x-a[i].x)*(a[i+1].x-a[i].x)+(a[i+1].y-a[i].y)*(a[i+1].y-a[i].y)+(a[i+1].z-a[i].z)*(a[i+1].z-a[i].z));
}
printf("%.3lf",d);
return 0;
}
这道题目有三点需要注意
1对题目的理解," 从第二个点开始,他经过的每一个点高度z都比上一个点高",这就表明不管如何输入,真正经过的点的顺序应该是按照z的由小到大的顺序排列
2.第一次排序时用了冒泡,但是当判断j与j+1时,j的范围是j<n-i,而j+1就等于了n-i,导致错误
3再次发现冒泡排序无法满足该题的时间要求,尝试多次后选择了快速排序,最后才满足了该题在时间上的要求,通过
本周因为对新知识点的学习做的题目比较少,但是总结的也都是本周做题的典型或常见错误,希望日后若再次出现类似错误时能快速找到错误的具体点和对应的解决方法.