您的位置:首页 > 其它

7.5.实验 解题参考

2016-07-05 11:28 232 查看
Problem-A(HDU1157)

排序水题,将输入数据排序用一次sort,输出中位数即直接输入第n/2个位置上的数。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[10010];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
printf("%d\n",a[n/2]);
}
return 0;
}


Problem-B(HDU1106)

这一题排序的部分很简单,将原串预处理分开,并逐一转换成数字,对这些数字sort一遍就可以输出了。

但是原串的预处理分割有点麻烦,需要考虑完备5出现的情况。

这里给出几组测试样例,这些都过了基本就考虑完全了:

555556 //开头有5的

1555556 //中间有一堆5的

125 //5结尾的

55552345891 //不是5结尾的

1234 //没有5的

12345531232 //不是5结尾的

每次遍历原串的每个位置,根据是否是5、出现5时位置与周边的情况决定分割。具体处理见标程。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
char s[10010];
int a[10010];

int change(string s)//将字符串转换成数字
{
int len = s.length();
int sum = 0;
for(int i = len - 1, j = 0; i >= 0; --i, ++j)
sum += (int)(s[i] - '0') * pow(10.0, j);
return sum;
}

int main()
{
int len, num;
string ans;
while(scanf("%s", s) != EOF)
{
len = strlen(s);
num = 0;
ans = "";
for(int i = 0; i < len; ++i)
{
if(s[i] != '5')
{
ans += s[i];
if(i == len - 1) //不是5结尾的
a[num++] = change(ans);
}
else if(s[i] == '5' && s[i - 1] != '5' && i != 0) //是5且不能一堆5且5不能为第一个
{
a[num++] = change(ans);
ans = "";
}
}
sort(a, a + num);
for(int i = 0; i < num - 1; ++i)
printf("%d ", a[i]);
printf("%d\n", a[num - 1]);
}
return 0;
}


Problem-C(HDU1031)

这一题需要做两趟排序,第一趟是对计算出的总满意度降序,排过之后可以确定能取到的前k项,但输出要求按编号降序,所有对前k个元素又要按条件再排序一次。

注意为排序方便,每个元素应该构造一个结构体,记录其总满意度和其编号。第一次排序对所有元素,所以范围是【a,a+m】,第二次是取前k个,所有范围是【a,a+k】。两次排序条件不一样,必须要自己写出两个比较函数(cmp1、cmp2)。

#include<iostream>
#include<algorithm>
using namespace std;
struct stu
{
double m;
int k;
};
int cmp1(stu a,stu b)
{
if(a.m!=b.m)
return a.m>b.m;
else
return a.k<b.k;
}
int cmp2(stu a,stu b)
{
return a.k>b.k;
}
int main()
{
int n,m,k;
double b;
int i;
stu s[10000];
while(cin>>n>>m>>k)
{
for(i=0;i<10000;i++) s[i].m=0;
while(n--)
{
for(i=0;i<m;i++)
{
cin>>b;
s[i].m+=b;
s[i].k=i;
}
}
sort(s,s+m,cmp1);
sort(s,s+k,cmp2);
for(i=0;i<k;i++)
{
cout<<s[i].k+1;
if(i<k-1)
cout<<' ';
}
cout<<endl;
}
return 0;
}


Problem-D

这道题有必要说一下题目大意了,稍有不慎就绕晕了TAT

题目大意:给你n个0~200之间的数,每个数对应有一个函数值,若所有的函数值出现的频率都相等而自变量不相等时是Bad,否则输出频率最高的函数值,若有多个升序输出。

前期处理很好做,就是输入一个数,将其转换为函数值存起来。

然后排序
4000
就好,但排完后是要看频率最高而不是当前数字大小。

那么可以对排好的顺序数组加个标签,相同的数排在一起正好可以累计计数,即每组相同的数最后一个的标记数出了其出现的总个数。

有了这个计数,找频率最高也就是找计数最大,引进一个变量m更新就好。

但可能有Bad的情况,那么再引进一个变量sm数出关联最大频率(一会可能要输出)的数的个数。如果最后它等于n,那么小心了,这说明所有函数值出现频率相等,肯是Bad。

为什么以上情况不能直接确定Bad呢(这也是我WA到落泪的地方),注意题意,频率都相同但数值有不相同才Bad,否则照常输出的。

所有可以通过刚刚的标记数组,看最后一个计数标记,若累计为n说明数字全一样,照常输出,多累计不为n才说明数值有不同的,所以符合(sm==n && num[n-1]!=n)的才是Bad情况。

出去Bad的情况,直接输出就很好输出了,从头到尾找一遍,如果标记计数等于最大值m,就是要输出的元素,为了调整换行格式,需要提前倒着找到最后一个,这是常见的输出小技巧。

具体见程序。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[1000000],num[1000000];
int main()
{
int T,t,n,m,sm,x;
scanf("%d",&T);t=0;
while(T--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&x);
a[i]=10000-(100-x)*(100-x);
}
sort(a,a+n);
for(int i=0;i<n;i++) num[i]=1;
for(int i=1;i<n;i++)
if(a[i]==a[i-1]) num[i]=num[i-1]+1;
m=0;sm=0;
for(int i=0;i<n;i++)
if(num[i]>m){m=num[i];sm=num[i];}
else if(num[i]==m) sm+=num[i];
t++;printf("Case #%d:\n",t);
if(sm==n && num[n-1]!=n) printf("Bad Mushroom\n");
else
{
int j=n-1;
while(num[j]!=m) j--;
for(int i=0;i<j;i++)
if(num[i]==m) printf("%d ",a[i]);
printf("%d\n",a[j]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  排序