度度想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同,度度想买一顶价格第三便宜的帽子,问第三便宜的帽子价格多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)
输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1
输入例子:
10
10 10 10 10 20 20 30 30 40 40
输出例子:
30
思路:set插入法。
#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int n;
cin>>n;
if(n<3)
{
cout<<-1<<endl;
return 0;
}
vector<int> v(n);
for(int i=0;i<n;i++)
cin>>v[i];
sort(v.begin(),v.end());
int j=0;
bool flag=0;
for(int i=1;i<n;i++)
{
if(v[j]!=v[i])
v[++j]=v[i];
if(j==2)
{
flag=1;
break;
}
}
if(flag)//若存在价格第三便宜的帽子
cout<<v[2];
else{
cout<<-1<<endl;
return 0;
}
return 0;
}
2 一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
思路:找出最长可以节省路径,再用总路径减去最大的可以节省路径即可。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
int n;cin>>n;
int result=0;
vector<int>temp(n,0);
cin>>temp[0];
for(int i=1;i<n;++i){
cin>>temp[i];
result+=abs(temp[i]-temp[i-1]); //在没有去除点时,总路程
}
int maxx=0;
for(int i=1;i<temp.size()-1;++i){
maxx=max(maxx,abs(temp[i]-temp[i-1])+abs(temp[i]-temp[i+1])-abs(temp[i+1]-temp[i-1])); //计算去掉中间点后 路程减少最多的距离
}
cout<<result-maxx<<endl; //总路程- 减少路程最多的即可
}
3 寻找三角形
问题:三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用'R', 'G', 'B'表示。
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。
4 度度熊有一个N个数的数组,他想将数组从大到小排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)
输出描述:
输出一个整数表示最少的操作次数。
输入例子:
4
19 7 8 25
输出例子:
2
思路:用map实现,数组中的数位map的键值,它的初始位置为value。在排好序的数组中,如果arr[i]<arr[i+1],但是map[arr[i]]>map[arr[i+1]],那就必须将arr[i+1]移动到最后的位置,然后更新arr[i+1]到原始位置,按照这样的过程遍历一遍,最后就是排好序的数组。
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n,val;
cin>>n;
vector<int> arr;
map<int,int> m;
for(int i=0;i<n;i++) {
cin>>val;
arr.push_back(val);
m[val]=i;
}
sort(arr.begin(),arr.end());
int index=n,count=0;
for(int i=0;i<n-1;i++) {
if(m[arr[i]] > m[arr[i+1]]) {
m[arr[i+1]]=index++;
count++;
}
}
cout<<count<<endl;
}
具体详见百度--有趣的排序
思路二:
从原序列中找出一组序列,该序列可以作为 排好序的序列中的前缀长度。eg:原序列为19 7 8 25,排序后是7 8 19 25,那么原序列中可以找到7 8这个序列,作为排序后 的序列中的前缀,再用序列长度减去这个前缀长度就是需要移动的次数。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int solve(vector<int> a) {
vector<int> b;
b=a;
sort(b.begin(),b.end());
int q,n=a.size()-1;
q=-1;
for(int i=0;i<=n;i++) {
if(a[i]==b[q+1]) {
q++;
if(q==n) break;
}
}
return n-q;
}
int main() {
int n,val;
cin>>n;
vector<int> arr;
for(int i=0;i<n;i++) {
cin>>val;
arr.push_back(val);
}
cout<<solve(arr)<<endl;
return 0;
}
5
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子:
66
基本思想:
定义数组dp[n][k]。其中,dp[i][j]表示有i个数字和j个"<"所能组成的数量,此时">"的数量为i-j-1。
当加入第i + 1个数字时,分以下四种情况:
1.如果将i+1插入当前序列的开头,即有了1<2,加入后成为3>1<2,会发现等于同时加入了一个">"。
2.如果将i+1插入当前序列末尾,即1<2变成了 1<2<3,会发现等于同时加入了一个"<"。
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-j-1个">",每个">"都要进行一次这样的操作。
合并同类项即为
dp[i][j] =dp[i - 1][j]+ dp[i - 1][j - 1]+dp[i - 1][j] * j+ dp[i - 1][j - 1] * (i- j - 1) =(dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1))
另外,定义dp[i][0]=1。
#include <bits/stdc++.h>
using namespace std;
int dp[1005][1005];
int main() {
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
dp[i][0] = 1;
}
for(int i = 2; i <= n; i++)
{
for(int j = 1; j <= k; j++)
{
dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;
}
}
cout << dp[n][k] % 2017 << endl;
return 0;
}