1044 Shopping in Mars

题目来源:PAT (Advanced Level) Practice

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:

  1. 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).
  2. Cut before 5 or after 6, and take off the diamonds from the position 4 to 6 (with values 5+4+6=15).
  3. 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 (≤10​5​​), the total number of diamonds on the chain, and M (≤10​8​​), the amount that the customer has to pay. Then the next line contains N positive numbers D​1​​⋯D​N​​ (D​i​​≤10​3​​ 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 ij 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 ij 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

word:

one by one 一个接一个,逐个的        exact 准确的        minimum 最小的,最低的        

sufficient 足够的        guarantee 保证,担保        

思路:

1. 本题要求从给定的n个数找出 i 和 j 使得从第i个数到第j个数的和刚好等于m,并输出所有满足的i、j对;若没有一组i、j对满足要求则输出从i到j的和大于m最小的数所对应的i、j对(所有i、j对);

2. 使用滑动窗口来来寻找满足要求的i、j对,其中i代表窗口的左端j代表窗口的右端,t 代表窗口内元素的和,初始为a[1] ,即窗口1-1;

        a. 当窗口内的和 t 小于m时,窗口右端向右移动,然后更新窗口内元素和 t ;

        b. 当窗口内的和 t 等于m时,输出当前的i、j对且窗口右端向右移动和标记flag=true,更新t;

        c. 当窗口内的和 t 大于m时,窗口左端向右移动并且判断当前窗口内值的和是否在当前为大于m的最小值 mi,若是则加入队列中并且删除队列中大于此值的i、j对;然后更新 mi 和 t;

3. 当flag==false时表示没有1个i、j对间的元素和等于m,所以输出队列中的所有元素;

4. 本题在提交时偶尔可能会出现超时现象,但是没有关系,再次提交即可;

//PAT ad 1044 Shopping in Mars
#include <iostream>
using namespace std;
#define N 100005
#include <deque>

deque<pair<int,string> > de; //用于保存没有结果时的最小结果 

void op_queue(int i,int j,int t)	//操作队列,将和为t的"i-j"加入队列,并且删除大于t的"i-j" 
{
	de.push_back({t,to_string(i)+"-"+to_string(j)});
	while(de.front().first>t)
		de.pop_front();
}

int main()
{
	int n,m,a[N],i,j;
	cin>>n>>m;
	for(i=1;i<=n;i++)	//输入 
		cin>>a[i];
		
	bool flag=false;	//标记是否有解 
	int mi=999999999;
	int t=a[1];			//t表示i到j的和(窗口内元素的和),初始为1到1,即a[1] 
	
	for(i=1,j=1;i<=n&&j<=n;)	//设置滑动窗口的两个指针i(窗口左端)和j(窗口右端)
	{
		if(t>m)		//若窗口元素的和大于m 
		{
			if(t<=mi)
			{
				mi=t;			//更新最小值 
				op_queue(i,j,t);	//操作队列,用于在无解的情况下输出最小值			
			} 
			t-=a[i];	i++;	//窗口左端右移,t更新 
		}			
		if(t==m)	
		{
			cout<<i<<"-"<<j<<endl;		//输出解 
			flag=true;		//标记有解 
			t-=a[i];	i++;	//窗口左端右移,t更新 
		}
		if(t<m)		//若窗口元素的和小于m
		{
			j++;	t+=a[j];	//窗口右端右移,t更新  
		}			
	}
	if(flag==false)	//无解情况时输出队列 
	{
		while(!de.empty())
		{
			string s=de.front().second;
			de.pop_front();
			cout<<s<<endl;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值