第1关:基金大师
- 任务要求
题目描述
小明热爱基金,现在给你某支基金的每天的价格,请你帮他算算买卖1次或0次所得最大利润是多少? (0次即没有发生交易)
输入输出:
第一个整数m(0<m<100)表示天数 第二组输入个m个整数,每个整数为每天的价格,每个的整数的范围为0到100000
输入: 6 7 1 5 3 6 4 输出: 5
本题来源,《算法导论》。本题考察动态规划-对过去信息充分利用的思想。变量minn代表历史最低值。cache表示当前基金值。
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
#include<cstring>
#include<sstream>
//#define int long long
using namespace std;
typedef long long ll;
const int N = 1000;
double dp[N + 10][N + 10];
int tu[N + 10][N + 10];
int num[N + 10];
int nex[200000];
int tong[120];
int32_t main() {
int n;
cin >> n;
int minn = 987654321;
int ans = 0;
for (int i = 1; i <= n; i++) {
int cache;
cin >> cache;
minn = min(minn, cache);
ans = max(ans, cache - minn);
}
cout << ans << endl;
}
第2关:奶茶店2
300
- 任务要求
题目描述
XTU奶茶店又开张了,现给定不同种类奶茶的储存量、总售价和需求量,现在请你计算该奶茶店所能获得的最大收益。
输入格式
每个输出包含一个测试样例,先给出一个N(0<N<=1000)表示奶茶的种类数,再给出一个D(0<D<=10000)表示市场最大需求量。随后两行分别是奶茶的库存量M(0<M<=10000)和每种奶茶的总售价P(0<P<=10000)。
输出格式
输出该奶茶店所能获得的最大收益,保留两位小数
输入样例
3 20 18 15 10 75 72 45
输出样例
94.50
本题考察贪心-利润。优先贩卖单价高的奶茶以便获得更多利润。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int arr[1010];
int brr[1010];
vector<pair<double, int>> v;
int main() {
int n, d;
cin >> n >> d;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int i = 1; i <= n; i++) {
cin >> brr[i];
}
for (int i = 1; i <= n; i++) {
v.push_back({brr[i]/(double)arr[i], arr[i]});
}
sort(v.begin(), v.end());
reverse(v.begin(),v.end());
double ans = 0;
for (auto it : v) {
ans+=it.first*min(it.second,d);
d-=min(it.second,d);
if(d==0)break;
}
printf("%.2lf",ans);
}
第3关:汇率大师
300
- 任务要求
描述
小明热衷于炒汇率,假设现在给你A币、B币、C币....等各个币种的兑换关系以及汇率,给你A币本金,请你帮小明算出兑换成最后一个币种的价值的最大值(以A币的价值表示)和最佳兑换路线。
注意:当存在不同路径的最大价值相同时,取路径短的,不存在价值和路径长度相同的样例。
输入说明:
先输入本金N(0<N<10000), 再输入兑换关系数量M(0<M<100)和币种数量H(0<H<26),接下来输入M行,每行的前两项是数字表示的币种,后面一项是汇率。
为简化题目,这里的汇率,可以理解为倍率,统一用正小数表示,例如本金100A币的时候,0 1 1.5 就可以理解为A币可以兑换价值150A币的B币.(保留小数点2位)
样例:
1.
输入: 100 1 2 0 1 1.5 输出: 150.00 A->B 说明: 这里是本金100,一个关系和两个币种
2.
输入: 100 9 6 0 1 2 0 2 1 0 3 6 1 2 1 1 4 1 2 4 2 3 2 5 3 4 8 4 5 1
输出: 6000.00 A->D->C->E->F
本题考察图论-图的遍历。数据量较小,dfs爆搜。注意保存路径长度和路径。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int arr[1010];
int brr[1010];
vector<pair<int, double>> edges[30];
int n, m, h;
double maxRate;
int ansPath[110];
int cachePath[110];
bool vis[30];
int ansDeep = 9999;
void dfs(int u, double proRate, int deep) {
cachePath[deep] = u;
if (u == h - 1) {
if (maxRate < proRate || (maxRate == proRate && ansDeep > deep)) {
maxRate = proRate;
ansDeep = deep;
for (int i = 1; i <= deep; i++) {
ansPath[i] = cachePath[i];
}
}
return;
}
for (auto it : edges[u]) {
int v = it.first;
double rate = it.second;
if (vis[v] == 0) {
vis[v] = 1;
dfs(v, proRate * rate, deep + 1);
vis[v] = 0;
}
}
}
int main() {
cin >> n >> m >> h;
for (int i = 1; i <= m; i++) {
int a, b;
double c;
cin >> a >> b >> c;
edges[a].push_back({b, c});
edges[b].push_back({a, 1 / c});
}
vis[0] = 1;
dfs(0, 1, 1);
cout.precision(2);
cout << fixed << n*maxRate << endl;
cout << "A";
for (int i = 2; i <= ansDeep; i++) {
cout << "->" << (char)(ansPath[i] + 'A');
}
}
第4关:铠甲锻造
300
- 任务要求
题目描述
一套铠甲的打造需要n种材料,编号为i的材料的坚硬度为ai(0<i<n),约定材料必须按照编号顺序依次放入冶炼炉,容量有限的冶炼炉同时最多只能容纳w个原料。但是我们可以在放入某个材料之前从冶炼炉种取出一些原料,取出的数量不能超过s个。
设: 编号为i的材料的耐久= 放入时冶炼炉内原料总数 * 材料坚硬度ai,铠甲的耐久为所有合成材料的耐久之和。
输入格式
line 1:3个整数n
w
s
line 2:n个整数 a1 … an
1 ≤ n ≤ 10^5 |ai| ≤ 10^7
输出格式
每行一个整数,为最大耐久度
输入输出样例
输入
5 3 3
1 3 2 4 5
输出
40
本题考察动态规划-01背包。考虑枚举将材料从锅中拿出的个数。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
long long a[5005];
long long dp[5005][5005];
int main() {
int s, w, n;
cin >> n >> w >> s;
for (int i = 1; i <= n; ++i)cin >> a[i];
memset(dp, 0xcf, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= w; ++j) {
for (int k = 0; k <= s; ++k) {
if (j + k - 1 <= w)
dp[i][j] = max(dp[i][j], dp[i - 1][j + k - 1] + a[i] * j);
}
}
}
long long ans = -0x3f3f3f3f3f3f3f3f;
for (int i = 1; i <= w; ++i) {
ans = max(ans, dp[n][i]);
}
cout << ans;
}
第6关:乌鸦爱收集
300
- 任务要求
题目背景
乌鸦Ozzy喜欢收集特殊的石头,今天的Ozzy也准备出门去收集喜欢的石头。
题目描述
Ozzy在小溪边饮水时,发现了溪边有一排特殊排列的石头,这些石头颜色分别为a1、a2、…、an,一共有 n 个,奥兹准备收集那些特殊的石头。
满足这些条件的这些条件的会被Ozzy认为特殊的石头:在给定的区间,并且在该区间内与它颜色相同石头的个数,与在该区间外这种颜色的石头的数量差 ≤给定常数K
请回答Ozzy的m个提问:区间[l,r]
中有多少不同颜色的特殊石头
输入格式
line 1:正整数n
m
k
line 2:n 个正整数,为石头的颜色 ti
之后 m 行,正整数l
r
0< l ≤ r < n
1 ≤ n ≤ 10^5 1 ≤ m ≤ 10^3 1 ≤ k ≤ 10^2
输出格式
m行,每个各一个整数表示询问的结果
输入输出样例
输入
6 9 10
13 11 1 12 11 11
4 4
4 4
0 0
3 5
2 5
1 4
2 4
5 5
3 3
输出
1
1
0
3
3
4
3
1
1
本题考察树状数组与扫描线这对经典cp的使用。需要用到扫描线思想,然后配合树状数组的区间修改和区间查询,以便实现离线处理询问,最后输出答案。当然也可以直接暴力求解。
#include<bits/stdc++.h>
using namespace std;
int a[100010];
int num[100010][100];
int flag[101];
int main()
{
int n,m,k;
memset(flag,0,sizeof(flag));
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
flag[a[i]]=1;
for(int j=1;j<=100;j++)
{
num[i][j]=num[i-1][j];
}
num[i][a[i]]++;
}
while(m--)
{
int l,r;
int temp=0;
scanf("%d %d",&l,&r);
for(int i=1;i<=100;i++)
{
if(abs((num[r][i]-num[l-1][i])-(num[n][i]-num[1][i]))<=k&&num[r][i]-num[l-1][i]!=0)
{
temp++;
}
}
printf("%d\n",temp);
}
}