PAT甲级-1044 Shopping in Mars

2024-09-06 21:36
文章标签 pat 甲级 mars 1044 shopping

本文主要是介绍PAT甲级-1044 Shopping in Mars,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

 

题目大意

一串项链上有n个钻石,输入给出每个钻石的价格。用m元买一个连续的项链子串(子串长度可为1),如果不能恰好花掉m元,就要找到最小的大于m的子串,如果有重复就输出多个,按递增顺序输出子串的前端和后端索引。

原来的思路

取连续的子串使和恰等于m,没有恰等于就找最小的大于。可以将子串依次累加,使得每个位置都是起始位置到该位置的序列和,整个数组显递增顺序,就可以用右边减左边的方式找到满足条件的子串。直接暴力for循环,这里我的数组从0开始,没有从1开始,所以又将满足条件的子串首端索引为0的情况单拎出来,很不推荐。其次还将等于m和大于m的情况拆开求解,设了个flag,如果前期有输出的话flag为1,没有输出flag为0时再考虑样例二。没有看成>=统一求解,也不推荐。所以就超时了。

原来的代码

#include <iostream>
#include <vector>
using namespace std;int main(){int n, money;cin >> n >> money;vector<int> v(n);for (int i = 0; i < (int)v.size(); i++){int num;cin >> num;i == 0 ? v[i] = num : v[i] = num + v[i - 1];}  // 这个思路很重要int flag = 0;for (int i = 0; i < (int)v.size(); i++){if (v[i] == money){cout << "1-" << i + 1 << endl;flag = 1;}}  // 查找从起始位置开始符合money的子串int maxi = 0;int q, h;  // 记录前后i的位置for (int i = 0; i < (int)v.size(); i++){for (int j = i - 1; j >= 0; j--){if (v[i] - v[j] == money){cout << j + 2 << "-" << i + 1 << endl;flag = 1;}else if (v[i] - v[j] > money){if (maxi < v[i] - v[j]){maxi = v[i] - v[j];q = j + 2;h = i + 1;}break;}}}if (flag == 0){cout << q << "-" << h << endl;for (int i = h; i < (int)v.size(); i++){for (int j = i - 1; j >= 0; j--){if (v[i] - v[j] == maxi){cout << j + 2 << "-" << i + 1 << endl;}else if (v[i] - v[j] > maxi){break;}}}} //测试样例2return 0;
}

思路

改进参考了柳神的代码。首先就是将数组容量改为n + 1,让钻石从1开始。之前我用了两个for循环,第一个遍历i,第二个遍历j,找满足v[j] - v[i] = m的值。数组是递增顺序,可以将第二个循环用二分法优化,即在给定区间找j。然后就是将等于m和大于m这两种情况合并成>=m,也即找到>=m的最小区间,定i找j,也就是找区间的最小右边界。这时就需要考虑结果的输出形式,不能边找边输出,只能用个数组存,如果有更小的边界值就清空数组重新放。

知识点

在二分查找中,如果要找某区间的最小边界,而不是具体的找某个值,while循环的条件就要设为low < high,如果要用二分查找找到某个值,条件就设为low <= high,此时循环最终范围缩小到1位。

如果要在函数中调用数组,要将该数组设成全局变量,如果设成局部变量不断引用,会占用大量堆栈空间,可能会超时。某个数的话设成局部变量还ok。

AC代码

#include <iostream>
#include <vector>
using namespace std;int n, money;
vector<int> v;  // 不设成全局变量就会超时void find_j(int i, int &j, int &mint){int high = n;int low = i;while (low < high){  // 二分查找最小满足条件的边界,所以不加=号int mid = (low + high) / 2;if (v[mid] - v[i - 1] < money){low = mid + 1;}else{high = mid;  // 这里保留mid,进一步缩小范围,因为mid也可能是最小索引}}j = high;  // high值才是最终的二分查找结果mint = v[j] - v[i - 1];
}  // 二分法找到满足条件的最小索引int main(){cin >> n >> money;v.resize(n + 1);for (int i = 1; i <= n; i++){int num;cin >> num;v[i] = num + v[i - 1];}  // 累加使得数组呈递增int mini = v[n];vector<int> res;for (int i = 1; i <= n; i++){int j, mint;  // i在前,j在后find_j(i, j, mint);  // 使用二分查找找到最小满足条件的jif (mint <= mini && mint >= money){if (mint < mini){mini = mint;res.clear();}res.push_back(i);res.push_back(j);}}for (int i = 0; i < (int)res.size(); i += 2){cout << res[i] << "-" << res[i + 1] << endl;}return 0;
}

 

 

这篇关于PAT甲级-1044 Shopping in Mars的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143181

相关文章

PAT (Advanced Level) Practice——1011,1012

1011:  链接: 1011 World Cup Betting - PAT (Advanced Level) Practice (pintia.cn) 题意及解题思路: 简单来说就是给你3行数字,每一行都是按照W,T,L的顺序给出相应的赔率。我们需要找到每一行的W,T,L当中最大的一个数,累乘的结果再乘以0.65,按照例子写出表达式即可。 同时还需要记录每一次选择的是W,T还是L

Eclipse4.X版本安装fatjar插件(luna mars 版本均可用)

首先声明,eclipse luna 和mars 楼主亲测可用。 1.安装Eclipse2.0版本的插件支持 方法如下: Help -> Install New Software... -> Work with -> 选择“The Eclipse Project Updates - http://download.eclipse.org/eclipse/updates/4.4

shopping黄金时代双11 你的服务架构还禁得住考验吗(3)

http://www.toutiao.com/a6351262826691150082/?tt_from=mobile_qq&utm_campaign=client_share&app=explore_article&utm_source=mobile_qq&iid=5840657922&utm_medium=toutiao_ios

PAT (Advanced Level) Practice

1001:  题目大意: 计算 a+b 的结果,并以标准格式输出——即每三个数字一组,组之间用逗号分隔(如果数字少于四位,则不需要逗号分隔)  解析: 我们知道相加右正有负,对于样例来说 Sample Input: -1000000 9 Sample Output: -999,991 如果是从左往右,算上负号的话输出应该是-99,999,1 从右往左:-,999,991离正确

1050 String Subtraction——PAT甲级

Given two strings S1​ and S2​, S=S1​−S2​ is defined to be the remaining string after taking all the characters in S2​ from S1​. Your task is simply to calculate S1​−S2​ for any given strings. However,

lightoj 1044 Palindrome Partitioning(dp)

题意:给定字符串S,问可以划分的最小回文串数量 思路:定义dp[i]为以i开头的字符串中回文串的最小划分数. dp[i] = min(dp[j] + 1 | i <= j < n && S[i...j]是回文串) 边界,dp[i] = n-i+1. /************************************************ Author: fisty* Crea

1105 链表合并——PAT乙级

给定两个单链表 L1​=a1​→a2​→⋯→an−1​→an​ 和 L2​=b1​→b2​→⋯→bm−1​→bm​。如果 n≥2m,你的任务是将比较短的那个链表逆序,然后将之并入比较长的那个链表,得到一个形如 a1​→a2​→bm​→a3​→a4​→bm−1​⋯ 的结果。例如给定两个链表分别为 6→7 和 1→2→3→4→5,你应该输出 1→2→7→3→4→6→5。 输入格式: 输入首先在第一

1110 区块反转——PAT乙级

给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。例如:给定 L 为 1→2→3→4→5→6→7→8,K 为 3,则输出应该为 7→8→4→5→6→1→2→3。 输入格式: 每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤105)、以及正整数 K (

PAT-1039 到底买不买(20)(字符串的使用)

题目描述 小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖。于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么告诉她有多少多余的珠子;如果不是,那么告诉她缺了多少珠子。为方便起见,我们用[0-9]、[a-z]、[A-Z]范围内的字符来表示颜色。例如,YrR8RrY是小红想做的珠串;那么ppRYYGrrYBR2258可以

PAT-1028

题目描述 某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是2014年9月6日,所以超过200岁的生日和未出生的生日都是不合理的,应该被过滤掉。 输入描述: 输入在第一行给出正整数N,取值在(0, 105];随后N行,每行给出1个人的姓名(由不超过5个