首页 > 编程语言 >*PAT_甲级_1044 Shopping in Mars (25分) (C++)【双指针】

*PAT_甲级_1044 Shopping in Mars (25分) (C++)【双指针】

时间:2022-10-27 16:00:14浏览次数:52  
标签:右移 25 Shopping 1044 int sum minSum ans data


目录

​1,题目描述​

​题目大意​

​输入​

​ 输出​

​说明​

​2,思路​

​核心思想​

​3,代码​


1,题目描述

*PAT_甲级_1044 Shopping in Mars (25分) (C++)【双指针】_C++

*PAT_甲级_1044 Shopping in Mars (25分) (C++)【双指针】_C++_02

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

题目大意

在火星上购买商品(熟悉的设定),需要用一串钻石(每颗代表一定的价值)来支付,但每次支付需要截取连续的一段,且一旦截取后,就不能再恢复原状。

以题目所给例子为例,M$3, 2, 1, 5, 4, 6, 8, 7, and we must pay M$15,因此可以有三种方法:

  • 3, 2, 1, 5, 4, 6, 8, 7;
  • 3, 2, 1, 5, 4, 6,
  • 3, 2, 1, 5, 4, 6, 8, 7;

输入

  1. 第一行:钻石数目N(<=10^5),支付的金额M(<=10^8);
  2. 第二行:钻石的价值(位置编号1-N);

 输出

  1. 所有可行的截取方案

说明

  • 若实在没有可以完全等于金额M的截取方法,则输出最小损失的截取方法 ;
  • Again all the solutions must be printed in increasing order of​​i:所有方案需按照编码的增序输出;​
  • It is guaranteed that the total value of diamonds is sufficient to pay the given amount.:确保钻石总的价值超过需要支付的金额;

2,思路

这一题还是有点复杂的。这位大佬的方法讲的很详细!​​@日沉云起【pat甲级-1044-Shopping in Mars (25)】​

这里借鉴大佬的第一种思路。时间复杂度为O(n).

核心思想

  • 设计左右两个指针i和j,在循环体中每次只移动一个
  • 当sum<M时,j右移
  • 当sum==M时,说明已找到完美方案,将minSum(存储最接近M的值)置为-1(这样就不会有比它更小的值了),并输出指针的位置(需要注意是否要减一);并将指针i右移
  • 当sum>M时,进一步判断minSum与sum的关系。若sum<minSum,说明有更接近M的答案,故重置minSum=sum,清空ans中的内容,并将当前左右指针存到ans中;若sum==minSum,将当前左右指针存入ans中。最后将指针i右移一位

 

3,代码

参考大神的第一种思路。

#include<iostream>
#include<vector>
#include<climits>
using namespace std;

int main(){
//#ifdef ONLINE_JUDGE
//#else
// freopen("1.txt", "r", stdin);
//#endif

int n, m; //n钻石数目 m支付金额
cin>>n>>m;

int data[100001];
for(int i = 1; i <= n; i++)
scanf("%d", &data[i]);

vector<pair<int, int>> ans; //当不存在完美方案时 保存所有额外开销最小的方案
int sum = 0, minSum = INT_MAX; //minSum用于判断距离m最近的值
for(int i = 1, j = 1; i <= n && j <= n + 1;){ //当j超过n时 而i未超过 仍可以继续进入循环
if(sum < m)
sum += data[j++];

else if(sum == m){
printf("%d-%d\n", i, j-1); //由于sum<m时 sum += data[j++] 所以当下一次sum==m时 j需要减一
minSum = -1; //表示不可能再被超过
sum -= data[i++]; //sum已达到m i右移且j停止移动(相当于将链缩短)
}

else{
if(sum < minSum){

minSum = sum;
ans.clear(); //更新最小方案
ans.push_back({i, j-1}); //由于sum<m时 sum += data[j++] 所以当下一次sum==m时 j需要减一
}else if(sum == minSum){ //保留开销最小且相同的方案
ans.push_back({i, j-1});
}
sum -= data[i++]; //sum已达到m i右移且j停止移动(相当于将链缩短)
}
}

if(minSum != -1){ //未找到完美方案
for(int i = 0; i < ans.size(); i++)
printf("%d-%d\n", ans[i].first, ans[i].second);
}
return 0;
}

 

标签:右移,25,Shopping,1044,int,sum,minSum,ans,data
From: https://blog.51cto.com/u_15849465/5801396

相关文章