目录
1,题目描述
题目大意
输入
输出
说明
2,思路
核心思想
3,代码
1,题目描述
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;
输入
- 第一行:钻石数目N(<=10^5),支付的金额M(<=10^8);
- 第二行:钻石的价值(位置编号1-N);
输出
- 所有可行的截取方案
说明
- 若实在没有可以完全等于金额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