请点击我学习提问技巧 C++实现有一批小娃,他们每人手上拿着一个数字,当然这个数字只有 1 位,也就是 0 到 9 之间。每个小娃的零花钱为在他之前的最长不下降子序列中所有数之和。 (这个序列必须以它作为结尾!)如有多个最长不下降子序列,那么取编号字典序最小的。现在告诉你有 n 个大朋友,以及他们各自的数字,请你求出他们每个人的分数。 输入格式 第一行,1 个数n。 第二行,n 个数,分别表示每个人的数字。 输出格式 一行,n 个数,分别表示每个人的零花钱。
时间: 2023-11-03 10:04:11 浏览: 43
算法思路:
我们可以使用动态规划来解决此问题。设 $dp[i]$ 表示以第 $i$ 个小朋友为结尾的最长不下降子序列和,$num[i]$ 表示第 $i$ 个小朋友手上的数字。则有转移方程:$$ dp[i]=\max_{j<i,num[j]\leq num[i]}{dp[j]}+num[i] $$ 其中 $\max_{j<i,num[j]\leq num[i]}{dp[j]}$ 表示以第 $i$ 个小朋友为结尾的最长不下降子序列和。
同时,我们需要用一个数组 $pre[i]$ 来记录以第 $i$ 个小朋友为结尾的最长不下降子序列的前一个小朋友的编号(如果有多个最长不下降子序列,则记录编号字典序最小的那一个)。这样,在最后输出答案时,我们就可以从最后一个小朋友开始,一直沿着 $pre$ 数组往前推,找到所有的小朋友,最终输出答案。
代码实现:
相关问题
用c++实现求一个数字的所有因子,要求时间和空间复杂度最小,我的数据包括1e18的数字
好的,这是一个计算问题,我可以帮您解答。关于一个数字的所有因子,可以使用试除法来得到所有因子。从2开始到这个数字的平方根,将这个数字不断除以当前的数,如果得到的商可以整除当前的数,则将这个商与当前的数都加入因子集合中。同时,对于平方数,还需要将平方根加入因子集合中。代码实现如下:
```c
#include <stdio.h>
#include <math.h>
int main(){
long long n = 1000000000000000000; // 输入的数字
long long factors[100], cnt = 0;
long long i, j;
for(i = 2; i <= sqrt(n); i++){
if(n % i == 0){
factors[cnt++] = i;
if(i != n / i) factors[cnt++] = n / i;
}
}
if(sqrt(n) * sqrt(n) == n) factors[cnt++] = sqrt(n);
for(i = 0; i < cnt; i++){
printf("%lld ", factors[i]);
}
return 0;
}
```
这里最耗时的操作就是求平方根,在很多情况下可以使用二分法来优化,但是图要求时间和空间复杂度最小,暴力求解已经足够了。 时间复杂度为O(sqrt(n)),空间复杂度为O(sqrt(n))。
8x8矩阵内存储1-9的数字,找到一个4x4方阵使其和最小。请用C++实现
这个问题可以使用回溯法进行求解。具体实现过程如下:
1. 首先定义一个8x8的二维数组,用来存储1-9的数字。
2. 然后定义一个4x4的二维数组,用来存储当前正在搜索的4x4方阵。
3. 接着定义一个变量minSum,用来存储当前找到的和最小的4x4方阵的和。
4. 定义一个递归函数,用来枚举所有可能的4x4方阵。函数的参数包括当前正在搜索的方阵的左上角坐标以及已经搜索到的数字的和。
5. 在递归函数中,首先检查当前搜索的4x4方阵是否超出了8x8的范围,如果是则直接返回。
6. 然后计算当前搜索的4x4方阵的数字和,如果比minSum小,则更新minSum。
7. 接着枚举当前搜索的4x4方阵中剩余的数字,并递归搜索下一个数字。
8. 最后返回minSum即可。
下面是代码实现:
```c++
#include <iostream>
using namespace std;
const int N = 8; // 8x8的矩阵
const int M = 4; // 4x4的方阵
int a[N][N]; // 存储1-9的数字
int b[M][M]; // 当前正在搜索的4x4方阵
int minSum = 0x3f3f3f3f; // 当前找到的和最小的4x4方阵的和
// 检查当前搜索的4x4方阵是否超出了8x8的范围
bool check(int x, int y) {
return x >= 0 && y >= 0 && x + M <= N && y + M <= N;
}
// 计算当前搜索的4x4方阵的数字和
int getSum() {
int sum = 0;
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
sum += b[i][j];
}
}
return sum;
}
// 递归函数,枚举所有可能的4x4方阵
void dfs(int x, int y, int sum) {
if (sum >= minSum) return; // 剪枝,如果当前搜索的数字和已经大于等于minSum,则返回
if (!check(x, y)) { // 如果当前搜索的4x4方阵超出了8x8的范围,则返回
minSum = min(minSum, sum); // 更新minSum
return;
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
b[i][j] = a[x + i][y + j]; // 枚举当前搜索的4x4方阵中剩余的数字
}
}
dfs(x + 1, y, sum + getSum()); // 递归搜索下一个数字
dfs(x, y + 1, sum + getSum());
}
int main() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> a[i][j]; // 输入数字
}
}
dfs(0, 0, 0); // 从左上角开始搜索
cout << minSum << endl; // 输出最小的数字和
return 0;
}
```
注意,这个算法的时间复杂度是指数级的,因此对于较大的矩阵可能会运行很长时间甚至超时。实际应用中需要根据具体情况进行优化。
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)