转载:2017百度春季实习生五道编程题[全AC]

装载至:https://blog.csdn.net/zmdsjtu/article/details/70880761

1【编程题】买帽子

 

时间限制:1秒
空间限制:32768K
度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)


输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1

输入例子:
10
10 10 10 10 20 20 30 30 40 40

输出例子:
30
代码1:更新最小三个数

 1 #include<iostream>
 2 using namespace std;
 3 void fun(){
 4     int n,x;
 5     int m1=1001,m2=1001,m3=1001;
 6     cin>>n;
 7     for(int i=0;i<n;++i){
 8         cin>>x;
 9         if(x<m1){
10             m1=x;
11         }
12         if(x>m1 && x<m2){
13             m2=x;
14         }
15         if(x>m2 && x<m3){
16             m3=x;
17         }
18     }
19     if(m1==1001||m2==1001||m3==1001)
20         cout<<-1;
21     else
22         cout<<m3;
23 }
24 int main(){
25     fun();
26     return 0;
27 }

方法2:使用标准模板库中的集合set

 1 #include<iostream>
 2 #include<set>
 3 using namespace std;
 4 int main(){
 5     int N;
 6     cin>>N;
 7     int price;
 8     set<int> prices;
 9     for(int ii=0;ii<N;++ii){
10         cin>>price;
11         prices.insert(price);
12     }
13     if(prices.size()<3){
14         cout<<-1<<endl;
15         return 0;
16     }
17     int cnt=2;
18     auto iter=prices.begin();
19     while(cnt--){
20         iter++;
21     }
22     cout<<*iter<<endl;
23     return 0;
24 }

2 [编程题] 度度熊回家
时间限制:1秒
空间限制:32768K
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。

接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100


输出描述:
输出一个整数表示度度熊最少需要走的距离。

输入例子:
4
1 4 -1 3

输出例子:
4
解题思路: 题目说法有些不准确,其实就是第一个点为当前位置,最后一个点为家,
需要依次走过这些点回家,可以跳过中间某一个点,求至少距离。
先求出走过所有的点的距离的总和 再求出跳过某个点后跳过的最大距离 
最后用总和减去跳过最大距离 就是跳过某个点后 至少走的最短距离
跳过某个点的距离为: |前一个点-这个点| +|这个点-后一个点|-|前一个点-后一个点|
//关键就是需要减去 前一个点到后一个点的距离 才是跳过这个点的距离

 1 #include<iostream>
 2 #include<algorithm>
 4 using namespace std;
 5 int main(){
 6     int n;
 7     cin>>n;
 8     float  buf[50];
 9     for(int i=0;i<n;++i){
10         cin>>buf[i];
11     }
12     float length=0;
13     for(int i=1;i<n;++i){
14         length=length+abs(buf[i]-buf[i-1]);
15     }
16     float max=0;
17     for(int i=1;i<n-1;++i){
18         float l=abs(buf[i]-buf[i-1])+abs(buf[i+1]-buf[i]);
19         l-=abs(buf[i+1]-buf[i-1]);
20         if(max<l){
21             max=l;
22         }
23     }
24     cout<<length-max<<endl;
25     return 0;
26 }

3 [编程题] 寻找三角形
时间限制:1秒
空间限制:32768K
三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用'R', 'G', 'B'表示。
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。
输入描述:
首先输入一个正整数N三维坐标系内的点的个数.(N <= 50)

接下来N行,每一行输入 c x y z,c为'R', 'G', 'B' 的其中一个。x,y,z是该点的坐标。(坐标均是0到999之间的整数)


输出描述:
输出一个数表示最大的三角形面积,保留5位小数。

输入例子:
5
R 0 0 0
R 0 4 0
R 0 0 3
G 92 14 7
G 12 16 8

输出例子:
6.00000

 1 #include<iostream>
 2 //#include<algorithm>
 3 #include<cmath>
 4 #include<vector>
 5 using namespace std;
 6 double result=0;
 7 double juli(vector<int>a,vector<int>b){
 8     int a1=a[0]-b[0];
 9     int a2=a[1]-b[1];
10     int a3=a[2]-b[2];
11     return sqrt((1.0*a1*a1)+(1.0*a2*a2)+(1.0*a3*a3));
12 }
13 double space(vector<int> a,vector<int> b,vector<int> c){
14     double a1=juli(a,b);
15     double a2=juli(a,c);
16     double a3=juli(b,c);
17     double p=(a1+a2+a3)/2.0;
18     return sqrt(1.0*p*(p-a1)*(p-a2)*(p-a3));
19 }
20 void updateResult(vector<vector<int>> a){
21     if (a.size() >= 3) {
22         for (int i = 0; i < a.size() - 2; ++i) {
23             for (int j = i + 1; j < a.size() - 1; ++j) {
24                 for (int z = j + 1; z < a.size(); ++z) {
25                     result = std::max(result, space(a[i], a[j], a[z]));
26                 }
27             }
28         }
29     }
30 
31 }
32 int main(){
33     int N;cin>>N;
34 
35     vector<vector<int>> R;
36     vector<vector<int>> G;
37     vector<vector<int>> B;
38     while(N--){
39         char temp;vector<int> a(3,0);
40         cin>>temp>>a[0]>>a[1]>>a[2];
41         if(temp=='R')R.push_back(a);
42         else if(temp=='G')G.push_back(a);
43         else if(temp=='B')B.push_back(a);
44     }
45     updateResult(R);
46     updateResult(G);
47     updateResult(B);
48     if(R.size()&&G.size() && B.size())
49         for(int i=0;i<R.size();++i)
50             for(int j=0;j<G.size();++j)
51                 for(int z=0;z<B.size();++z)
52                     result=max(result,space(R[i],G[j],B[z]));
53     printf("%.5f",result);
54     return 0;
55 }

4 [编程题] 有趣的排序
时间限制:1秒
空间限制:32768K
度度熊有一个N个数的数组,他想将数组从大到小排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)


输出描述:
输出一个整数表示最少的操作次数。

输入例子:
4
19 7 8 25

输出例子:
2

 


思路:

例如 19 7  8  25 的正确顺序是7 8 19 25  可以发现7-8顺序是对的,但8-17是错的,所以只能保持7-8不变,其余的都需要动,所以是4-2次

 

同理,如果一个n个数字组成的序列,从小到大,前m个是稳定的,那么最终结果就是n-m

 1 #include<iostream>
 2 #include<algorithm>  
 3 #include<vector>
 4 #include<map>
 5 using namespace std;
 6 int main(){
 7     int n;cin>>n;
 8     vector<int>temp(n,0);
 9     map<int,int>mapping;
10     for(int i=0;i<n;++i){
11         cin>>temp[i];
12         mapping[temp[i]]=i;
13     }
14     sort(temp.begin(),temp.end());
15     int i=0;
16     while(i+1<=n-1&&mapping[temp[i]]<mapping[temp[i+1]]){
17         ++i;
18     }
19     cout<<n-i-1<<endl;
20 }

5[编程题] 不等式数列
时间限制:1秒
空间限制:32768K
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)


输出描述:
输出满足条件的排列数,答案对2017取模。

输入例子:
5 2

输出例子:
66

解:参考:https://blog.csdn.net/qq_30629571/article/details/72626634

dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;
dp[i][j]表示有i个数字及j个小于号所能组成的数量(大于号数量当然是i - j - 1次,后面需要使用)
而加入第i + 1个数字时,分以下四种情况:
1.如果将i+1插入当前序列的开头,即有了1<2,加入后成为3>1<2,会发现等于同时加入了一个大于号!(此时可以无视1与2之间的关系,因为i+1>i)
2.如果将i+1插入当前序列末尾,即1<2变成了 1<2<3,会发现等于同时加入了一个小于号! (此时可以无视1与2之间的关系,因为i+1>i)
3.如果将i+1加入一个小于号之间,即已经有 1<2了,向中间加入3,会发现变成了1<3>2,等于同时加入了一个大于号!
4.如果将i+1加入一个大于号中间,即有了2>1,变成了2<3>1,等于同时加入了一个小于号!
综上所述,dp[i][j]等于以上四种情况之和:
dp[i - 1][j]                                     //将i加在开头等于加入一个大于号,即要求i-1个数时已经有了j个小于号
dp[i - 1][j - 1]                               //将i加在末尾等于加入一个小于号,即要求i-1个数时已经有了j-1个小于号
dp[i - 1][j] * j                                //将i加在任意一个小于号之间,等于加入了一个大于号;即要求i-1个数时已经有了j个小于号,每个小于号都可以进行这样的一次插入
dp[i - 1][j - 1] * (i- j - 1)              //将i加载任意一个大于号之间,等于加入了一个小于号;即要求i-1个数时有了j-1个小于号,而此时共有
                                                       (i - 1) - (j - 1)- 1个大于号,每个大于号都要进行一次这样的操作
合并同类项即为
 dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1))

 1 #include <iostream>
 2 #include <vector>
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int n, k;
 9     cin >> n >> k;
10     vector<vector<int>> dp(n + 1, vector<int>(n+1, 0));
11     dp[2][0] = 1;
12     dp[2][1] = 1;
13     for (int i = 3; i <= n; ++i)
14     {
15         dp[i][0] = 1;
16         dp[i][i - 1] = 1;
17     }
18     for (int i = 3; i <= n; ++i){
19         for (int j = 1; j <= i - 2; ++j)
20         {
21             dp[i][j] = (dp[i - 1][j - 1] *(i - j))%2017 + (dp[i - 1][j] *(j + 1))%2017;
22         }
23     }
24     cout << dp[n][k]%2017 << endl;
25     return 0;
26 }

 

posted @ 2019-07-09 10:39  知了会爬树  阅读(294)  评论(0编辑  收藏  举报