zoukankan      html  css  js  c++  java
  • PAT 甲级 1044 Shopping in Mars (25 分)(滑动窗口,尺取法,也可二分)

    1044 Shopping in Mars (25 分)
     

    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 (≤), the total number of diamonds on the chain, and M (≤), the amount that the customer has to pay. Then the next line contains N positive numbers D1​​DN​​ (Di​​103​​ for all ,) 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 > with (Di + ... + Dj −) 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

    题意:

     找到和不小于一个给定值、但尽可能小的所有子串

    题解:

     两个指针,分别指向子串头尾,具体看代码(有优化,比如说找到一个满足要求的子串后,下一次扫描左指针右移一位,右指针的起始位置就保持在上一次右指针的位置即可)。

    1.使用尺取法,如果取得范围总和大于需要pay的,删掉头部

    2.如果取得范围综合小于pay的,增加尾部

    3.注意边界情况和没有相等的情况,细节可查看代码

    4.利用一个minAns的变量进行记录答案数值

    AC代码:

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    int a[100005];
    int ans[100005];//数组开小了就测试点3一直不过
    int k=0;
    int n,m;
    int cha=0x7fffffff;
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        int r=1,l=1;
        int s=0;
        while(r<=n){
            while(s<m&&l<=n){
                s+=a[l];
                l++;
            }
            if(s<m){
                break;
            }
            else if(s<cha){
                k=0;
                ans[++k]=r;
                ans[++k]=l-1;
                cha=s;
            }else if(s==cha){
                ans[++k]=r;
                ans[++k]=l-1;
            }
            s-=a[r];
            r++;
        }
        for(int i=1;i<=k;i+=2){
            cout<<ans[i]<<"-"<<ans[i+1]<<endl;
        }
        return 0;
    } 

    也可以用二分:

    因为所有钻石价值为正,因此从开始到某位置的链条价值和恒正,在读入价值时进行累加;

    从第一个位置出发用二分法找到恰好大于或等于目标值的位置,并计算差值进行比较;

    如有差值更小的数据组,则更新记录;如找到差值恰好的数据组,加入记录;

    按照题目要求输出结果,并返回零值。

    #include<cstdio>
    #include<fstream>
    const int N=100010;
    int sum[N];
    int n, S, nears=100000010;
     
    int upper_bound(int L, int R, int x){
        int left=L, right=R, mid;
        while(left<right){
            mid=(left+right)/2;
            if(sum[mid]>x){
                right=mid;
            } else{
                left=mid+1;
            }
        }
        return left;
    }
     
    int main(){
    //    freopen("d://in.txt","r",stdin);
        scanf("%d%d", &n, &S);
        sum[0]=0;
        for(int i=1; i<=n; i++){
            scanf("%d", &sum[i]);
            sum[i]+=sum[i-1];
        }
        
        for(int i=1; i<=n; i++){
            int j=upper_bound(i, n+1, sum[i-1]+S);
            if(sum[j-1]-sum[i-1]==S){
                nears=S;
                break;
            } else if(j<=n && sum[j]-sum[i-1]<nears){
                nears=sum[j]-sum[i-1];
            }
        }
        
        for(int i=1; i<=n; i++){
            int j=upper_bound(i, n+1, sum[i-1]+nears);
            if(sum[j-1]-sum[i-1]==nears){
                printf("%d-%d
    ", i, j-1);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    PAT 甲级 1051 Pop Sequence (25 分)(模拟栈,较简单)
    PAT 甲级 1050 String Subtraction (20 分) (简单送分,getline(cin,s)的使用)
    PAT 甲级 1049 Counting Ones (30 分)(找规律,较难,想到了一点但没有深入考虑嫌麻烦)***...
    PAT 甲级 1048 Find Coins (25 分)(较简单,开个数组记录一下即可)
    PAT 甲级 1047 Student List for Course (25 分)(cout超时,string scanf printf注意点,字符串哈希反哈希)...
    PAT 甲级 1046 Shortest Distance (20 分)(前缀和,想了一会儿)
    R语言实现金融数据的时间序列分析及建模
    ES6 | class类的基本语法总结
    less使用总结
    umi 的项目中如何修改 favicon
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/11446367.html
Copyright © 2011-2022 走看看