✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1044 Shopping in Mars (pintia.cn)
🔑中文翻译:火星购物
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
1044 Shopping in Mars
Shopping in Mars is quite a different experience. The Mars people pay by chained diamonds. Each diamond has a value (in Mars dollars M$). When making the payment, the chain can be cut at any position for only once and some of the diamonds are taken off the chain one by one. Once a diamond is off the chain, it cannot be taken back. For example, if we have a chain of 8 diamonds with values M$3, 2, 1, 5, 4, 6, 8, 7, and we must pay M$15. We may have 3 options:
- Cut the chain between 4 and 6, and take off the diamonds from the position 1 to 5 (with values 3+2+1+5+4=15).
- Cut before 5 or after 6, and take off the diamonds from the position 4 to 6 (with values 5+4+6=15).
- Cut before 8, and take off the diamonds from the position 7 to 8 (with values 8+7=15).
Now given the chain of diamond values and the amount that a customer has to pay, you are supposed to list all the paying options for the customer.
If it is impossible to pay the exact amount, you must suggest solutions with minimum lost.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤105), the total number of diamonds on the chain, and M (≤108), the amount that the customer has to pay. Then the next line contains N positive numbers D1⋯DN (Di≤103 for all i=1,⋯,N) which are the values of the diamonds. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print
i-j
in a line for each pair ofi
≤j
such that Di
+ … + Dj
= M. Note that if there are more than one solution, all the solutions must be printed in increasing order ofi
.If there is no solution, output
i-j
for pairs ofi
≤j
such that Di
+ … + Dj
>M with (Di
+ … + Dj
−M) minimized. Again all the solutions must be printed in increasing order ofi
.It is guaranteed that the total value of diamonds is sufficient to pay the given amount.
Sample Input 1:
16 15 3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13
Sample Output 1:
1-5 4-6 7-8 11-11
Sample Input 2:
5 13 2 4 5 7 9
Sample Output 2:
2-4 4-5
题意
给定 N
个数的序列 Di+…+Dj
和一个常量 M
,让我们输出所有区间和等于 M
的方案。
每行输出一种可行方案,具体格式为 i-j
,表示 Di+…+Dj=M
。
如果方案不唯一,则按照 i
递增的顺序输出所有方案。
如果无法准确凑出 M
,仍然输出 i-j
,表示 Di+…+Dj>M
并且 Di+…+Dj−M
的值最小。
如果方案不唯一,则按照 i
递增的顺序输出所有方案。
思路
这道题需要用到前缀和和双指针算法,先对序列求前缀和并存到数组 s
中。
然后先求大于等于M
的最小区间和 res
,因为可能不存在等于 M
的区间和。
最后再去遍历所有区间,输出所有等于 res
的区间和方案。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, INF = 0x3f3f3f3f;
int s[N];
int n, m;
int main()
{
scanf("%d%d", &n, &m);
//求前缀和
for (int i = 1; i <= n; i++)
{
scanf("%d", &s[i]);
s[i] += s[i - 1];
}
//找到大于等于m的最小值
int res = INF;
for (int i = 1, j = 0; i <= n; i++)
{
//如果s[i]-s[j+1]>=m,则s[i]-s[j]也一定大于等于m,所以直接j++即可
while (s[i] - s[j + 1] >= m) j++;
if (s[i] - s[j] >= m) res = min(res, s[i] - s[j]);
}
//找到区间和等于res的所有方案
for (int i = 1, j = 0; i <= n; i++)
{
while (s[i] - s[j + 1] >= m) j++;
if (s[i] - s[j] == res) printf("%d-%d\n", j + 1, i);
}
return 0;
}