[编程题] 寻找三角形
时间限制: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
暴力计算,穷举
#include <iostream>
#include <vector>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <string>
#include <limits.h>
#include <cmath>
#include <iomanip>
using namespace std;
double Area(double a,double b,double c)
{
double s = (a + b + c) / 2;
return sqrt(s*(s - a)*(s - b)*(s - c));
}
double CountTri(vector<vector<int>> vec)
{
int len = vec.size();
if (len < 3)
return 0;
double min = 0;
for (int i = 0; i < len; ++i)
{
for (int j = i + 1; j < len; ++j)
{
for (int k = j + 1; k < len; ++k)
{
double a = pow(vec[i][0] - vec[j][0], 2) + pow(vec[i][1] - vec[j][1], 2) + pow(vec[i][2] - vec[j][2], 2);
double b = pow(vec[i][0] - vec[k][0], 2) + pow(vec[i][1] - vec[k][1], 2) + pow(vec[i][2] - vec[k][2], 2);
double c= pow(vec[j][0] - vec[k][0], 2) + pow(vec[j][1] - vec[k][1], 2) + pow(vec[j][2] - vec[k][2], 2);
double temp = Area(sqrt(a),sqrt(b), sqrt(c));
if (temp > min)
min = temp;
}
}
}
return min;
}
int main()
{
int count;
cin >> count;
vector<vector<int>> R;
vector<vector<int>> G;
vector<vector<int>> B;
while (count--)
{
string str;
cin >> str;
if (str == "R")
{
int x;
vector<int> temp;
for (int i = 0; i <= 2; ++i){
cin >> x;
temp.push_back(x);
}
R.push_back(temp);
}
if (str == "G")
{
int x;
vector<int> temp;
for (int i = 0; i <= 2; ++i){
cin >> x;
temp.push_back(x);
}
G.push_back(temp);
}
if (str == "B")
{
int x;
vector<int> temp;
for (int i = 0; i <= 2; ++i){
cin >> x;
temp.push_back(x);
}
B.push_back(temp);
}
}
double Rmax = CountTri(R);
double Gmax = CountTri(G);
double Bmax = CountTri(B);
double sum = 0;
for (int i = 0; i < R.size(); ++i){
for (int j = 0; j < G.size(); ++j)
{
for (int k = 0; k < B.size(); ++k)
{
vector<vector<int>> temp;
temp.push_back(R[i]);
temp.push_back(G[j]);
temp.push_back(B[k]);
double area = CountTri(temp);
if (area > sum)
sum = area;
}
}
}
double res=max(max(Rmax, Gmax), max(Bmax, sum));
cout << fixed << setprecision(5) << res << endl;
return 0;
}
[编程题] 不等式数列
时间限制:1秒
空间限制:32768K
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 ‘>’ 和 ‘<’ )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即(‘<”)和n-k-1个大于符号(即’>’),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子:
66
动态规划 对于从1-n,k个小于号的合法组合数记为dp[n][k],假设已经知道dp[n-1][k],那么一定是在1-n-1,k个小于号组成的排列中增加一个大于号和n,那么一定是添加在有小于号的空当中以及行首,每种排列有(k+1)中放的位置,或者是dp[n-1][k-1],也就是说要把n和一个小于号放在1-n-1的合法序列中,这一定是放到有大于号的位置中以及最后,这就包括n-k中情况,所以可以得到递推式:
dp[n][k]=dp[n-1][k](k+1)+dp[n-1][k-1](n-k);
之后直接利用动态规划的方法递推即可.代码比较简单
#include <iostream>
#include <vector>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <limits.h>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
vector<vector<int>> dp(n + 1, vector<int>(n+1, 0));
dp[2][0] = 1;
dp[2][1] = 1;
for (int i = 3; i <= n; ++i)
{
dp[i][0] = 1;
dp[i][i - 1] = 1;
}
for (int i = 3; i <= n; ++i){
for (int j = 1; j <= i - 2; ++j)
{
dp[i][j] = (dp[i - 1][j - 1] *(i - j))%2017 + (dp[i - 1][j] *(j + 1))%2017;
}
}
cout << dp[n][k]%2017 << endl;
return 0;
}