题目名称:
买帽子
题目描述:
度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)
输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1
输入:
10
10 10 10 10 20 20 30 30 40 40
输出:
30
题意:
题目描述
题解:
set搞一搞
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
const int maxn = 1000 + 5;
int main(){
int n,x;
while(scanf("%d",&n)!=EOF){
set<int> s;
for(int i = 1; i <= n; i ++){
scanf("%d",&x);
s.insert(x);
}
if(s.size() < 3) printf("-1\n");
else{
set<int>::iterator it;
int k = 1;
for(it = s.begin (); it != s.end (); it ++){
if(k == 3) printf("%d\n",*it);
k ++;
}
}
}
return 0;
}
题目名称:
度度熊回家
题目描述:
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。
接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100
输出描述:
输出一个整数表示度度熊最少需要走的距离。
输入:
4
1 4 -1 3
输出:
4
题意:
题目描述
题解:
暴力枚举
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
const int maxn = 100 + 5;
int a[maxn];
int main(){
int n;
while(scanf("%d",&n)!=EOF){
int maxx = 100000;
for(int i = 0; i < n; i ++){
scanf("%d",&a[i]);
}
int dis = 0;
for(int i = 1; i < n; i ++){
dis += abs(a[i] - a[i - 1]);
}
//cout<<dis<<endl;
for(int i = 1; i < n - 1; i ++){
int d = abs(a[i] - a[i - 1]) + abs(a[i] - a[i + 1]);
int cnt = dis - d;
int t = abs(a[i - 1] - a[i + 1]);
cnt += t;
maxx = min(maxx,cnt);
}
printf("%d\n",maxx);
}
return 0;
}
题目名称:
寻找三角形
题目描述:
三维空间中有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
题意:
题目描述
题解:
直接知道三角形面积的计算公式就很好做了
S=(1/2)(x1y21+x2y31+x3y11-x1y31-x2y11-x3y2*1)
然后就是分颜色相同枚举和颜色全不同枚举
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
struct Point{
char c;
double x, y, z;
};
bool cmp(Point p1, Point p2){
return p1.c < p2.c;
}
double pointDistance(Point p1, Point p2){
double distance = 0;
distance = sqrt((p1.y - p2.y)*(p1.y - p2.y) + (p1.x - p2.x)*(p1.x - p2.x) + (p1.z - p2.z)*(p1.z - p2.z));
return distance;
}
double area(Point p1, Point p2, Point p3){
double area = 0;
double a = 0, b = 0, c = 0, s = 0;
a = pointDistance(p1, p2);
b = pointDistance(p2, p3);
c = pointDistance(p1, p3);
s = 0.5*(a + b + c);
area = sqrt(s*(s - a)*(s - b)*(s - c));
return area;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
//getchar();
vector<Point> v(n);
char c;
int x, y, z;
int cntR = 0, cntG = 0, cntB = 0;
double ans = 0;
for(int i = 0; i < n; i++){
cin>>v[i].c>>v[i].x>>v[i].y>>v[i].z;
//scanf("%c %d %d %d",&v[i].c,&v[i].x,&v[i].y,&v[i].z);
//getchar();
//cout<<v[i].c<<endl;
if (v[i].c == 'R') cntR ++;
if (v[i].c == 'G') cntG ++;
if (v[i].c == 'B') cntB ++;
}
sort(v.begin(), v.end(), cmp);
if(cntB >= 3){
for (int i = 0; i < cntB; i++){
for (int j = i + 1; j < cntB; j++){
for (int k = j + 1; k < cntB; k++){
ans = max(ans, area(v[i], v[j], v[k]));
}
}
}
}
if(cntG >= 3){
for (int i = 0; i < cntG; i++){
for (int j = i + 1; j < cntG; j++){
for (int k = j + 1; k < cntG; k++){
ans = max(ans, area(v[cntB + i], v[cntB + j], v[cntB + k]));
}
}
}
}
if(cntR >= 3){
//cout<<"R"<<endl;
for (int i = 0; i < cntR; i++){
for (int j = i + 1; j < cntR; j++){
for (int k = j + 1; k < cntR; k++){
ans = max(ans, area(v[cntB + cntG + i], v[cntB + cntG + j], v[cntB + cntG + k]));
}
}
}
}
for(int i = 0; i < cntB; i++){
for (int j = cntB; j < cntB + cntG; j++){
for (int k = cntB + cntG; k < n; k++){
ans = max(ans, area(v[i], v[j], v[k]));
}
}
}
printf("%.5f\n", ans);
}
return 0;
}
题目名称:
有趣的排序
题目描述:
度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)
输出描述:
输出一个整数表示最少的操作次数。
输入:
4
19 7 8 25
输出:
2
题意:
题目描述
题解:
先建一个map,记录原数组各个数值的索引,然后排序,在排序后的数组中找到前面一个数的索引比后面一个的大,那么后面的这个数就应该插到原数组的最后,并且索引数更新为n++,算一次操作,循环遍历排序后的数组即可得到总的操作次数。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<iostream>
using namespace std;
const int maxn = 100 + 5;
int main(){
int n,x;
while(scanf("%d",&n)!=EOF){
vector<int> v;
map<int,int> mp;
for(int i = 0; i < n; i ++){
scanf("%d",&x);
v.push_back(x);
mp[x] = i;
}
int ans = 0,idx = n;
sort(v.begin(),v.end());
for(int i = 0; i < n - 1; i ++){
if(mp[v[i]] > mp[v[i + 1]]){
mp[v[i + 1]] = idx ++;
ans ++;
}
}
printf("%d\n",ans);
}
return 0;
}
题目名称:
不等式数列
题目描述:
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 ‘>’ 和 ‘<’ )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即(’<’’)和n-k-1个大于符号(即’>’),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入:
5 2
输出:
66
题意:
题目描述
题解:
dp[i][j] 表示i个序列有j个’<’,对于i+1个序列,可以进行如下分析
1.直接添加到最开始,此时多添加一个>,种类数+dp[i-1][j];
2.直接添加到最后面,此时多添加一个<,种类数+dp[i-1][j-1];
3.添加到中间任意一个<,例如1<2,变成1<3>2,多添加了一个>,种类数+dp[i-1][j]j;
4.添加到中间任意一个>,例如2>1,变成2<3>1,多添加了一个<,种类数+dp[i-1][j-1](i-j-1)
整理可得到:dp[i][j] = dp[i-1][j](j+1)+dp[i-1][j-1](i-j)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1000 + 5;
int dp[maxn][maxn];
int main() {
int n,k;
while(scanf("%d%d",&n,&k)!=EOF){
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;
}
printf("%d\n",dp[n][k] % 2017);
}
return 0;
}