PAT B1049

这篇具有很好参考价值的文章主要介绍了PAT B1049。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PAT B1049

题目

给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 这 10 个片段。

给定正整数数列,求出全部片段包含的所有的数之和。如本例中 10 个片段总和是 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0。

输入格式:

输入第一行给出一个不超过 10^5 的正整数 N,表示数列中数的个数,第二行给出 N 个不超过 1.0 的正数,是数列中的数,其间以一个空格分隔。

输出格式:

在一行中输出该序列所有片段包含的数之和,精确到小数点后 2 位。

输入样例:

4
0.1 0.2 0.3 0.4

输出样例:

5.00

尝试:

我的第一眼感觉是一个子集问题,但是它又不是所有的子集,首先打印出所有的子集,根据出现的子集,判断所有子集中,哪些应该存在,哪些不应该存在。

#include <bits/stdc++.h>

using namespace std;

void subsets(vector<double>&arr,vector<double>&path,vector<vector<double> >&res,int k,int n) {
    if (k == n) {
        return;
    }
    path.push_back(arr[k]);
    res.push_back(path);
    subsets(arr, path, res, k + 1, n);
    path.pop_back();
    subsets(arr, path, res, k + 1, n);
}




int main() {
    int n;
    cin>>n;
    vector<double>arr;
    for (int i = 0; i <n ; ++i) {
        double t;
        cin>>t;
        arr.push_back(t);
    }
    vector<double>path;
    vector<vector<double> >res;
    subsets(arr,path,res,0,n);
    for (int i = 0; i < res.size(); ++i){
        for (int j = 0; j <res[i].size() ; ++j) {
            cout<<" ["<<res[i][j]<<"] ";
        }
        cout<<"\n";

    }




    return 0;


}

在输出里,我们需要的子集使用’#'标记

4
0.1 0.2 0.3 0.4
 #[0.1]          
 #[0.1]  [0.2]     
 #[0.1]  [0.2]  [0.3]        
 #[0.1]  [0.2]  [0.3]  [0.4] 
 [0.1]  [0.2]  [0.4]        
 [0.1]  [0.3] 
 [0.1]  [0.3]  [0.4]
 [0.1]  [0.4]
 #[0.2]
 #[0.2]  [0.3]
 #[0.2]  [0.3]  [0.4]
 [0.2]  [0.4]
 #[0.3]
 #[0.3]  [0.4]
 #[0.4]


找到了一个规律,如果path为空,你可以随便放入一个元素,如果不为空,你必须放入path刚放进去的元素的后一位元素(即如果path里最新放入的元素为num[i-1],你就只能放num[i],要么就不放)

这里放入元素还需要记录数组下标,所以我这里使用pair,你也可以自己设计一个结构体,或者直接使用数组当作结构体

#include <bits/stdc++.h>

using namespace std;

void
subsets(vector<double> &arr, vector<pair<int, double> > &path,
        vector<vector<pair<int, double> > > &res, int k, int n) {
    if (k == n) {
        return;
    }
    //如果path为空直接放入
    if (path.size() == 0) {
        path.push_back(make_pair(k, arr[k]));
        res.push_back(path);
        subsets(arr, path, res, k + 1, n);
        path.pop_back();
        subsets(arr, path, res, k + 1, n);
    } else {
        //如果不为空
        if (path[path.size() - 1].first == k - 1) {
            path.push_back(make_pair(k, arr[k]));
            res.push_back(path);
            subsets(arr, path, res, k + 1, n);
            path.pop_back();
            subsets(arr, path, res, k + 1, n);

        }


    }


}


int main() {
    int n;
    cin >> n;
    vector<double> arr;
    for (int i = 0; i < n; ++i) {
        double t;
        cin >> t;
        arr.push_back(t);
    }
    vector<pair<int, double> > path;
    vector<vector<pair<int, double> > > res;
    subsets(arr, path, res, 0, n);

    for (int i = 0; i < res.size(); ++i) {
        for (int j = 0; j < res[i].size(); ++j) {
            cout << " [" << res[i][j].second << "] ";
        }
        cout << "\n";

    }


    return 0;


}

4
0.1 0.2 0.3 0.4
 [0.1]
 [0.1]  [0.2]
 [0.1]  [0.2]  [0.3]        
 [0.1]  [0.2]  [0.3]  [0.4] 
 [0.2]
 [0.2]  [0.3]
 [0.2]  [0.3]  [0.4]        
 [0.3]
 [0.3]  [0.4]
 [0.4] 

实现了选择子集功能

初步实现

#include <bits/stdc++.h>

using namespace std;

void
subsets(vector<double> &arr, vector<pair<int, double> > &path,
        vector<vector<pair<int, double> > > &res, int k, int n) {
    if (k == n) {
        return;
    }
    //如果path为空直接放入
    if (path.size() == 0) {
        path.push_back(make_pair(k, arr[k]));
        res.push_back(path);
        subsets(arr, path, res, k + 1, n);
        path.pop_back();
        subsets(arr, path, res, k + 1, n);
    } else {
        //如果不为空
        if (path[path.size() - 1].first == k - 1) {
            path.push_back(make_pair(k, arr[k]));
            res.push_back(path);
            subsets(arr, path, res, k + 1, n);
            path.pop_back();
            subsets(arr, path, res, k + 1, n);

        }


    }


}


int main() {
    int n;
    cin >> n;
    vector<double> arr;
    for (int i = 0; i < n; ++i) {
        double t;
        cin >> t;
        arr.push_back(t);
    }
    vector<pair<int, double> > path;
    vector<vector<pair<int, double> > > res;
    subsets(arr, path, res, 0, n);
    double sum=0;

    for (int i = 0; i < res.size(); ++i) {
        for (int j = 0; j < res[i].size(); ++j) {
          sum+=res[i][j].second;
        }
    }
    std::printf("%.2f",sum);


    return 0;


}

提交结果:

PAT B1049

内存不够用,需要优化一下代码

初步优化

#include <bits/stdc++.h>

using namespace std;

double check(vector<double> arr, vector<int> path) {
    double tmp = 0;
    for (int i = 0; i < path.size(); ++i) {
        tmp += arr[path[i]];
    }
    return tmp;
}


void
subsets(vector<double> &arr, vector<int> &path,
        double &sum, int k, int n) {
    if (k == n) {
        return;
    }
    //如果path为空直接放入
    if (path.size() == 0) {
        path.push_back(k);
        sum += arr[k];
        subsets(arr, path, sum, k + 1, n);
        path.pop_back();
        subsets(arr, path, sum, k + 1, n);
    } else {
        //如果不为空
        if (path[path.size() - 1] == k - 1) {
            path.push_back(k);
            sum += check(arr, path);
            subsets(arr, path, sum, k + 1, n);
            path.pop_back();
            subsets(arr, path, sum, k + 1, n);

        }


    }


}


int main() {
    int n;
    cin >> n;
    vector<double> arr;
    for (int i = 0; i < n; ++i) {
        double t;
        cin >> t;
        arr.push_back(t);
    }
    vector<int> path;
    double sum = 0;
    subsets(arr, path, sum, 0, n);
    std::printf("%.2f", sum);


    return 0;


}
提交结果:

PAT B1049

这下内存没超,时间超了,还得优化,死磕了呀!!!

把数据结构都删掉再试试

#include <bits/stdc++.h>

using namespace std;

void
subsets(vector<double> &arr, int &last_index,
        double &sum, double &path_sum, int k, int n) {
    if (k == n) {
        return;
    }
    //如果path为空直接放入
    if (last_index == -1) {
        last_index = k;
        path_sum += arr[k];
        sum += arr[k];
        subsets(arr, last_index, sum, path_sum, k + 1, n);
        last_index = -1;
        path_sum -= arr[k];
        subsets(arr, last_index, sum, path_sum, k + 1, n);
    } else {
        //如果不为空
        if (last_index == k - 1) {
            last_index = k;
            path_sum += arr[k];
            sum += path_sum;
            subsets(arr, last_index, sum, path_sum, k + 1, n);
            last_index = k - 1;
            path_sum -= arr[k];
            subsets(arr, last_index, sum, path_sum, k + 1, n);

        }


    }


}


int main() {
    int n;
    cin >> n;
    vector<double> arr;
    for (int i = 0; i < n; ++i) {
        double t;
        cin >> t;
        arr.push_back(t);
    }
    double sum = 0;
    double path_sum = 0;
    int last_index = -1;
    subsets(arr, last_index, sum, path_sum, 0, n);
    std::printf("%.2f", sum);


    return 0;


}
提交结果:

PAT B1049

最后两个还是没过,超时,感觉自己好弱

再次优化

感觉这种搜索有点难过最后两个样例了,得输入的时候就处理数据,在O(n)内就把数据处理完,这样模拟的应该跑不了的,尝试下数学方法规律

#include <bits/stdc++.h>

using namespace std;


int main() {
    int n;
    cin >> n;
    double sum = 0;
    for (int i = 0; i < n; ++i) {
        double t;
        cin >> t;
        sum += t * (n - i) * (i + 1);//样例从左到右要加(4-i)*(i+1)次 比如用第一个元素从左到右一共用4次 只能向右边片段3次本身一次
        //第二个元素前面使用从0开始到4结束使用第二个元素一共使用5次片段 本身用一次 一共六次
    }

    printf("%.2f", sum);


    return 0;


}



提交结果:

PAT B1049

没过,绷不住了

查了下,测试点2错误double的精度不够,易产生误差,数据量足够大误差就会被放大直至小数点后2位也不精确。

最终代码

#include <bits/stdc++.h>

using namespace std;


int main() {
    int n;
    cin >> n;
    long double sum = 0.0;
    for (int i = 0; i < n; ++i) {
       double t;
        cin >> t;
        sum += t * (n - i) * (i + 1);//样例从左到右要加(4-i)*(i+1)次 比如用第一个元素从左到右一共用4次 只能向右边片段3次本身一次
        //第二个元素前面使用从0开始到4结束使用第二个元素一共使用5次片段 本身用一次 一共六次
    }

    printf("%.2f",(double) sum);


    return 0;


}



提交结果:

PAT B1049

终于过了!!! 慢慢加油吧!文章来源地址https://www.toymoban.com/news/detail-431890.html

到了这里,关于PAT B1049的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023-05-25:给定一个正整数 x,我们将会写出一个形如 x (op1) x (op2) x (op3) x ... 的表达式 其中每个运算符 op1,op2,… 可以是加、减、乘、除之一 例如

    2023-05-25:给定一个正整数 x,我们将会写出一个形如 x (op1) x (op2) x (op3) x ... 的表达式 其中每个运算符 op1,op2,… 可以是加、减、乘、除之一 例如,对于 x = 3,我们可以写出表达式 3 * 3 / 3 + 3 - 3,该式的值为3 在写这样的表达式时,我们需要遵守下面的惯例: 除运算符(/)

    2024年02月06日
    浏览(41)
  • 题目:2185.统计包含给定前缀的字符串

    ​​ 题目来源:         leetcode题目,网址:2185. 统计包含给定前缀的字符串 - 力扣(LeetCode) 解题思路:        遍历判断即可。 解题代码: 总结:         官方题解也是一样的思路。

    2024年02月15日
    浏览(56)
  • C语言题目:阶乘数列求和(函数)

    输入一个正数x和一个正整数n,求下列算式的值。要求定义两个调用函数:fact(n)计算n的阶乘;mypow(x,n)计算x的n次幂(即xn),两个函数的返回值类型是double。       x - x2/2! + x3/3! + ... + (-1)n-1xn/n! ×输出保留4位小数。 x n 数列和 定义 fact 函数 : fact(int n) 函数用于计算一个整数

    2024年04月13日
    浏览(51)
  • 【LeetCode题目详解】第九章 动态规划 part05 1049. 最后一块石头的重量 II 494. 目标和 474.一和零(day43补)

    有一堆石头,用整数数组  stones 表示。其中  stones[i] 表示第 i 块石头的重量。 每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为  x 和  y ,且  x = y 。那么粉碎的可能结果如下: 如果  x == y ,那么两块石头都会被完全粉碎; 如果  x != y

    2024年02月09日
    浏览(36)
  • 算法---缺失的第一个正数

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 借用map 就可以实现,但是如果不借用map,在原空间上,也可以实现,不过想要使用原来的数据,会有侵略性,会把原来的数据修改掉。 方法一: 方法二: 算法是很看一个人的思维逻辑的,所以很多

    2024年02月06日
    浏览(36)
  • LeetCode41.缺失的第一个正数

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。   示例 1: 输入:nums = [1,2,0] 输出:3 示例 2: 输入:nums = [3,4,-1,1] 输出:2 示例 3: 输入:nums = [7,8,9,11,12] 输出:1 思路: 1.本

    2024年02月12日
    浏览(40)
  • leetcode 41. 缺失的第一个正数

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 输入:nums = [1,2,0] 输出:3 示例 2: 输入:nums = [3,4,-1,1] 输出:2 示例 3: 输入:nums = [7,8,9,11,12] 输出:1 提示: 1 = nu

    2024年02月15日
    浏览(40)
  • LeetCode 41 缺失的第一个正数

    缺失的第一个正数 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 示例 2: 示例 3: 提示: 1 = nums.length = 5 * 105 -231 = nums[i] = 231 - 1 如果本题没有额外的时空复杂度要求

    2024年01月17日
    浏览(36)
  • Leetcode41缺失的第一个正数

    思路:原地哈希表 长度为N的数组,没有出现过的正整数一定是1~N+1中的一个。 此时会思考能不能用一个哈希表来保存出现过的1~N+1的数,然后从 1 开始依次枚举正整数,并判断其是否在哈希表中 但是题目要求常数级别的空间,就不能使用N的哈希表了。 这里将原数组当做哈

    2024年02月05日
    浏览(36)
  • 41. 缺失的第一个正数 --力扣 --JAVA

    给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 对数组进行排序,便于查看是否连续; 因为是最小正整数,所以判断值应从1开始; 只要当前元素值大于最小值,则直接返回最

    2024年02月06日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包