**
A - 前m大的数
还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。
// 把N个数放进数组cout,将其中元素两两相加的和放进一个数组so,最后将数组so中的数进行从大到小的排序,按照题目要求输出前M个数
```cpp
**#include<iostream>
#include<algorithm>
using namespace std;
int N,M,i,k,j=0,so[4500000],cont[3000];
bool cmp(int a,int b) //将数组元素从大到小排列
{
return a>b;
}
int main()
{
while (scanf("%d %d",&N,&M) != EOF){
for(i=0;i<N;i++)
scanf("%d",&cont[i]);
for(i=0;i<N-1;i++){
for(k=i+1;k<N;k++){
so[j++]=cont[i]+cont[k]; //so[j]为数组cout中任意两数之和总共(N*N-1)/2个
}
}
sort(so,so+j,cmp);
for(i=0;i<M;i++){
printf("%d",so[i]);
if(i !=M-1 ) printf(" "); //经过排序后,输出前M个数,也就是较大的M个数
}
cout<<endl;
}
return 0;
}
B - 稳定排序
大家都知道,快速排序是不稳定的排序方法。
如果对于数组中出现的任意a[i],aj,其中a[i]==a[j],在进行排序以后a[i]一定出现在a[j]之前,则认为该排序是稳定的。
某高校招生办得到一份成绩列表,上面记录了考生名字和考生成绩。并且对其使用了某排序算法按成绩进行递减排序。现在请你判断一下该排序算法是否正确,如果正确的话,则判断该排序算法是否为稳定的。
// 用到结构体,要使稳定可以在结构体中加入int 类型的数代表顺序序号,通过sort函数进行排序,如果分数相等序号在前的先输出,最后满足题目要求输出
**
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct student //定义结构体
{
char name[50];
int score;
int pl; //pl代表输入的顺序的序号
}stu1[300],stu2[300]; //stu1代表初始学生信息,stu2代表经过某算法得出的结果
int N,i,k;
bool cmp(student a,student b){ //将学生信息按照分数以及序号进行排序
if(a.score != b.score)
return a.score>b.score;
else
return a.pl<b.pl;
}
int main()
{
while(scanf("%d",&N) != EOF ){
for(i=0;i<N;i++){
scanf("%s %d",stu1[i].name,&stu1[i].score);
stu1[i].pl=i;
}
for(i=0;i<N;i++)
scanf("%s %d",stu2[i].name,&stu2[i].score);
sort(stu1,stu1+N,cmp); //对stu1中的学生进行排序
for(i=0;i<N;i++){ //对比tu2与排列好的stu1中的分数
if(stu2[i].score != stu1[i].score) {
printf("Error\n"); //如果不一致,输出Error
for(k=0;k<N;k++)
printf("%s %d\n",stu1[k].name,stu1[k].score);
break;
}
}
if(i==N) //在此表示两者分数一致,比较tu2与排列好的stu1中的学生姓名
for(i=0;i<N;i++){
if(strcmp(stu2[i].name,stu1[i].name) !=0 ){
printf("Not Stable\n"); //如果不一致,输出Not Stable
for(k=0;k<N;k++)
printf("%s %d\n",stu1[k].name,stu1[k].score);
break;
}
}
if(i==N) printf("Right\n"); //在此表示两者学生信息完全一致,输出Right
}
return 0;
}
C - 开门人和关门人
每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签
到、签离记录,请根据记录找出当天开门和关门的人。
// 通过分别比较M个人 进入机房的早晚 和 离开机房的早晚 可以得出开门和关门的人是谁,输出他们的名字即可。比较时间正好可以定义时间为字串,通过比较字符串的大小确定早晚
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct student //分别定义进入机房人的姓名,进入时间,离开时间
{
char name[20];
char begin[10];
char end[10];
}stu[10000];
bool cmp1(student a,student b){ //对进入机房时间进行从小到大排序,序列的第一个即为开门的人
return strcmp(a.begin,b.begin)<0;
}
bool cmp2(student a,student b){ //对离开机房时间进行从大到小排序,序列的第一个即为开门的人
return strcmp(a.end,b.end)>0;
}
int main()
{
int N,k=0,M,Y,i;
scanf("%d",&N);
while(N--) //N为天数
{
scanf("%d",&M); //M为人数
for(i=0;i<M;i++)
{
scanf("%s %s %s",stu[i].name,stu[i].begin,stu[i].end);
}
sort(stu,stu+M,cmp1); //排序
printf("%s ",stu[0].name); //输出开门的人
sort(stu,stu+M,cmp2); //排序
printf("%s\n",stu[0].name); //输出关门的人
}
return 0;
}
E - {A} + {B}
给你两个集合,要求{A} + {B}.
注:同一个集合中不会有两个相同的元素.
// 把A B集合元素放在一起,进行从小到大排序,只输出连续相同元素中其中一个即可
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,i,N[100000];
int main()
{
while(scanf("%d %d",&n,&m) != EOF){ //n,m分别为两个集合元素数目
for(i=0;i<n+m;i++){ //将它们放在N数组中输入值
scanf("%d",&N[i]);
}
sort(N,N+n+m); //sort函数默认从小到大paixv
printf("%d",N[0]);
for(i=1;i<n+m;i++)
if(N[i] != N[i-1]) printf(" %d",N[i]); //如果连续两个数相等,则跳过后面这个数
printf("\n");
}
return 0;
}
**
G - 不重复数字
给出N个数,要求把其中重复的去掉,只保留第一次出现的数。
例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。
// 将给出的数放进一个数组,用数组中第 i 个元素与该数组中第 i 个元素之前的 i-1个元素进行比较,如果这些元素中有元素与第 i 个元素相等,则跳过这个数不进行输出,直到数组元素结束。
**
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int T,N,i,k,num[50000];
cin>>T;
while(T--){ //T代表次数
cin>>N;
for(i=0;i<N;i++){
cin>>num[i];
}
for(i=0;i<N;i++){
for(k=i-1;k>=0;k--)
if(num[i] == num[k]) break; //如果第 i 个元素与 i 之前的任一元素相等则跳过这个数
if(k==-1) //k=-1 代表第 i 个数之前没有数与之相等,则输出这个数
cout<<num[i]<<" ";
}
cout<<"\n";
}
return 0;
}
**
H - 表达式括号匹配
给出一个表达式,该表达式仅由字符(、)、+、-以及数字组成。
请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回"YES";否则返回"NO"。
// 比较输入元素当中 ‘(’ 与 ‘)’ 个数是否相等,相等即匹配,不相等即不匹配
```cpp
#include<iostream>
#include<algorithm>
using namespace std;
int find(char x[2000],char c){ //定义函数,返回字符数组中所要求的字符个数
int count=0;
for(int i=0;x[i] != '\0';i++)
if(x[i]==c) count++;
return count;
}
int main(){
char x[2000];
int j=0;
while(scanf("%c",&x[j]) && x[j] != '\n')
j++;
if(find(x,'(') == find(x,')')) printf("YES"); //比骄 ‘(’ 与 ‘)’字符个数输出YES或NO
else printf("NO");
return 0;
}
**
I - 合并果子**
**
现在有n堆果子,第i堆有ai个果子。现在要把这些果子合并成一堆,每次合并的代价是两堆果子的总果子数。求合并所有果子的最小代价。
// 先将较小的两堆果子合并成一堆,再将现有的 i-1 堆果子中较小的两堆合并成一堆,知道只剩下一堆果子,求得最小代价
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int P,T,n,i,count[1000],so[50]={0},q=0;
scanf("%d",&T); //输入 T 组数据
P=T;
while(P--)
{
scanf("%d",&n); //输入 n 堆果子
for(i=0;i<n;i++)
scanf("%d",&count[i]);
for(;n>=2;n--)
{
sort(count,count+n,cmp); //将 n 堆果子数量从大到小排序
count[n-2]=count[n-1]+count[n-2]; //将最后两堆果子放在一堆
so[q]=so[q]+count[n-2]; //so代表代价
}
q++;
}
for(i=0;i<T;i++)
printf("%d\n",so[i]);
return 0;
}