Shopping in Mars is quite a different experience. The Mars people pay by chained diamonds. Each diamond has a value (in Mars dollars M ).Whenmakingthepayment,thechaincanbecutatanypositionforonlyonceandsomeofthediamondsaretakenoffthechainonebyone.Onceadiamondisoffthechain,itcannotbetakenback.Forexample,ifwehaveachainof8diamondswithvaluesM 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 of i <= j such that Di + … + Dj = M. Note that if there are more than one solution, all the solutions must be printed in increasing order of i.
If there is no solution, output “i-j” for pairs of i <= j such that Di + … + Dj > M with (Di + … + Dj - M) minimized. 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.
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*n的复杂度上进行优化,用到了几个点是我没考虑到的。
1.当i~j的区间上的和等于m之后,i+1~j区间上的情况就不用考虑了
2.对于找不到等于m的情况,在找到某个区间i~j之和大于m之后,就可以跳出j的循环,从i+1为起点的区间再开始寻找,因为之后的区间i~j+1……..i~n累加的和更大,不用考虑。
再加上c的输入输出的效率优化已经足够了。
自己写的程序一开始有一个情况没考虑到,导致优化之后最后一个点一直错误,就是在没有找到区间和等于m的情况之前就发现了区间和大于m的情况,使对最后输出的结果需要筛选一下。
#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
struct pairs{
int begin;
int end;
int num;
};
bool cmp(const pairs p1, const pairs p2){
if (p1.num < p2.num){
return true;
}
else if (p1.num == p2.num){
if (p1.begin < p2.begin){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
int main(){
for (int n, m; scanf("%d%d", &n, &m) != EOF;){
int *arr = new int[n + 1];
int i;
int j;
arr[0] = 0;
int total = 0;
for (i = 1; i <= n; i++){
int temp;
scanf("%d", &temp);
total += temp;
arr[i] = total;
}
vector<pairs>vec;
int flag = 0;
int jmp = 0;
for ( i = 1; i <= n; i++){
if (flag && i <= jmp){
j = jmp+1;
}
else{
jmp = 0;
j = i;
}
for (; j <= n; j++){
if (arr[j] - arr[i - 1] == m){
pairs p;
p.begin = i;
p.end = j;
p.num = arr[j] - arr[i - 1];
vec.push_back(p);
flag = 1;
jmp = j;
break;
}
else if (arr[j] - arr[i - 1] > m&& !flag){
pairs p;
p.begin = i;
p.end = j;
p.num = arr[j] - arr[i - 1];
vec.push_back(p);
//测试点3是 >m的情况
break;
}
}
}
sort(vec.begin(), vec.end(),cmp);
if (vec.size()){
int check = vec[0].num;
for (i = 0; i < vec.size(); i++){
if (vec[i].num == check){
printf("%d-%d\n", vec[i].begin, vec[i].end);
}
else{
break;
}
}
}
}
return 0;
}