1.扎银花
两组数据比大小,取出最大的三个数比较他们的和,输出和更大的那个数,如果一样,也输出。
- 使用内置的sort比手写bubblesort只取前三个更快?
2.最长上升子串构造
从序列中删除一个数,求所有的删除方案中,最长上升子串(连续的)的长度。
#include"pch.h"
#include <iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> num(n);
vector<int> len(n);//以当前节点为首,最长连续递增子序列长度
vector<int> start(n);//当前节点为尾,最长连续递增子序列的首位置
len[n - 1] = 1;
start[0] = 0;
int maxx = 0;
for (int i = 1; i < n; i++) {
if (num[i] < num[i - 1]) start[i] = start[i - 1];
else start[i] = i;
}
for (int i = n - 2; i >= 0; i--) {
if (num[i] < num[i + 1]) {
len[i] = len[i - 1] + 1;
maxx = max(len[i], maxx);
}
else len[i] = 1;
}
int res = 0;
for (int i = 1; i < n; i++) {
if (num[i - 1] < num[i + 1]) {
int tmp = len[i + 1] + start[i-1] - i;
maxx = max(tmp, maxx);
}
}
cout << maxx;
return 0;
}
3.做任务
n个任务,对于每个任务都有k个子任务,每个子任务花费的时间与父任务无关,只与出现顺序有关,每个父任务、子任务都只能完成一次,完成一个子任务会给p分,完成一个任务的k个子任务后,会得到额外的q分,求m时间内,最大得分。
#include"pch.h"
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
/*3.n个任务,对于每个任务都有k个子任务,
每个子任务花费的时间与父任务无关,
只与出现顺序有关,每个父任务、子任务都只能完成一次,
完成一个子任务会给p分,完成一个任务的k个子任务后,
会得到额外的q分,求m时间内,最大得分*/
int main() {
int n, k, m, p, q;
cin >> n >> k >> m >> p >> q;
vector<int> jobs(k);//k个子任务
long res = 0;
long sum = 0;//单个任务总时长
for (int i = 0; i < k; i++) {
cin >> jobs[i];
sum += jobs[i];//统计一个父任务的总时长
}
sort(jobs.begin(), jobs.end());
int l = (int)(m / sum);//最多能完成几个父任务
if (n < l) l = n;
for (int i = 0; i <= l; i++) {
long time = m - sum * i;//完成i个父任务后还剩多少时间
long score = i * (p*k + q);//完成i个父任务的总分
int remain = n - i;//剩下多少个父任务没有完成
for (int j = 0; j < k; j++) {//尝试完成子任务
if (jobs[j] * remain > time) {
//剩余时间t < 完成剩余父任务的第j个子任务
score += ((time / jobs[j])*p);
//得得分数+剩余时间能够完成的第j个子任务的个数
break;
}
else {
time -= jobs[j] * remain;
//剩余时间够的话,就减去完成剩余父任务所有j子任务的时间
score += p * remain;
}
}
if (score > res) res = score;
}
cout << res;
return 0;
}
4. 跑步
准备正好跑k距离,城市道路可以看成n个点,m条无向边组成的无向图,每边由固定的长度。
跑步前往一个目的地时一定要走最短距离,如果正好跑k距离,能够到达的目的地的个数,目的地可能在图的点上,也可能在边上,且该目的地距离他起点的最短路径正好k距离。
若k大于所有路径之和,自然没有这样的目的地,返回0。
示例:点数,边数,起点编号,m行无向边:u->v,w长度,下一行:k
3 3 1
1 2 2
2 3 3
1 3 4
4
输出:2,目的地是编号3的点,以及在2->3路径2/3处的一个点。
#include"pch.h"
#include <iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 1000;
const int INF = 1000000;
int n, m, k;
int d[maxn], w[maxn][maxn],g[maxn][maxn];
int vis[maxn] = { 0 };
void dijkstra(int s) {
fill(d, d + maxn, INF);
d[s] = 0;
int i, j, v;
for (i = 0; i < n; i++) {
int u = -1;
int min = INF;
for (j = 0; j < n; j++) {
if (vis[j] == 0 && d[j] < min) {
u = j; min = d[j];
}
}
if (u == -1) return;
vis[u] = 1;
for (v = 0; v < n;v++) {
if (vis[v] == 0 && g[u][v]!=INF) {
if (d[v] > d[u] + g[u][v]) {
d[v] = d[u] + g[u][v];
}
}
}
}
}
int main() {
int s;
cin >> n >> m >> s;
fill(g[0], g[0] + maxn * maxn, INF);
for (int i = 0; i < n; i++) {
int a, b, c;
cin >> a >> b >> c;
g[a-1][b-1] = c;
g[b-1][a-1] = c;
}
cin >> k;
dijkstra(s-1);
int res = 0;
for (int i = 0; i < n; i++) {
if (d[i] == k) res++;//cout << d[i] << " ";
}//s到每个点的最短距离
//再求,到各个边上点的情况
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (g[i][j] == INF) continue;
if (d[i]<k && d[i] + g[i][j]>k) {
int tmp = d[i] + g[i][j] - k;
if (d[j] + tmp >= k) res++;
}
}
}
cout << res;
return 0;
}
- 不知道对不对
- 利用dijkstra,先求起点到其余各点的最短距离
- 再求在边上的情况,u-v这条边,dis[u]<k && dis[u]+g[u][v]>k,且从u到达比从v到达这个点要近,就是说这个边上的这个点,最短距离是从u来的,也算是一种情况
5.序列最长不下降子序列
1,0,0,1,1的最长不下降子序列是0,0,1,1
某序列只有1和0,完成(1)某段区间的0变成1,(2)求整段序列的最长不下降子序列长度,每组操作后都会对序列造成改变,就是说整个序列会不停变化。
输入:n,m,序列长度和查询次数 (n:[1,100000],m:[1,100000],x,y:[1,n])
n行无空格的数字,只有0或1
m行个询问,两个操作的询问方式:(1)c x y 将区间[x,y]的0变为1,1变为0(2)q 询问整段序列的最长不下降子序列长度。(整个序列下标:1,2,3,...,n)
输出:对于q类询问,输出最长不下降自序列长度
示例:
5 5
10011
q 长度:4
c 1 5 修改后变成:01100
q 长度:3
c 1 3 修改后变成:10000
q 长度:4
输出:4 3 4