zoukankan      html  css  js  c++  java
  • PAT——甲级1046S:shortest Distance

    这道题,折磨了我一个多小时,前前后后写了三个算法。

    1046 Shortest Distance (20 point(s))

    The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains an integer N (in [3,105​​]), followed by N integer distances D1​​D2​​ ⋯ DN​​, where Di​​ is the distance between the i-th and the (i+1)-st exits, and DN​​ is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (104​​), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107​​.

    Output Specification:

    For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

    Sample Input:

    5 1 2 4 14 9
    3
    1 3
    2 5
    4 1
    

    Sample Output:

    3
    10
    7

     题目特很简单,就是一个多个点组成的环形,求两个点之间的最短距离。阳历第一行5代表5个点,后面第i个数代表第一个点到第i+1个点的距离。等等。。。

    然后我第一个想法是循环链表,第一次完成的写链表的代码,废了九牛二虎之力,写了一个循环链表,然后就贼舒服的求最短距离。

    先贴出来的我写的代码

    #include<cstdio>
    class Node
    {
    public:
        int num;
        int dis;
        Node* next;
        Node* pre;
    };
    
    class cycleLinkList
    {
    public:
        cycleLinkList();
        void insert_back(int num, int dis);
        int find_nearest(int prenum,int lastnum);
        //void displayAll(void);
    private:
        Node* head;
    };
    cycleLinkList::cycleLinkList() 
    { 
        head = new Node;
        head->num = 0;
        head->pre = head;
        head->next = 
        head;head->dis = 0; 
    }
    void cycleLinkList::insert_back(int num, int dis) {
        Node* pre = head->next;
        while (pre->next!=head)
        {
            pre = pre->next;
        }
        Node* new_Node=new Node;
        new_Node->dis = dis;
        new_Node->num = num;
        new_Node->next = head;
        new_Node->pre = pre;
        pre->next->pre = new_Node;
        pre->next = new_Node;
    }
    int cycleLinkList::find_nearest(int prenum, int lastnum) {
        Node* pre = head->next;
        while (pre->num != prenum)
        {
            pre = pre->next;
        }
        int predistance=0,nextdistance=0;
        Node* pre_dir = pre;
        while (pre_dir->num != lastnum)
        {
            pre_dir = pre_dir->pre;
            predistance += pre_dir->dis;
            
        }
        Node* next_dir = pre;
        while (next_dir->num != lastnum)
        {
            nextdistance += next_dir->dis;
            next_dir = next_dir->next;
        }
        if (nextdistance >= predistance)return predistance;
        else return nextdistance;
    
    }
    /*
    void cycleLinkList::displayAll(void)
    {
        Node* _head = head->next;
        while (_head != head)
        {
            printf("%d  %d
    ", _head->num, _head->dis);
            _head = _head->next;
        }
        printf("pre
    ");
        _head = head->pre;
        while (_head != head)
        {
            printf("%d  %d
    ", _head->num, _head->dis);
            _head = _head->pre;
        }
    }*/
    
    int main()
    {
        int n,m,dis;
        scanf("%d", &n);
        cycleLinkList data;
        for (int i = 0; i < n; i++){
            scanf("%d", &dis);
            data.insert_back(i + 1, dis);
        }
        //data.displayAll();
        //printf("insert");
        scanf("%d", &m);
        for (int i = 0; i < m; i++){
            int pre_num, last_num;
            scanf("%d%d", &pre_num,&last_num);
            printf("%d
    ",data.find_nearest(pre_num, last_num));    
        }
        return 0;
    }

    写完之后运行很正常,当然是很舒服啦,但是。。。提交给OJ就是运行超时,我也很无奈,循环链表那么直观,竟然不让用。

    那我就用数组呗,第二个想法,用数组。

     1 #include<cstdio>
     2 int main()
     3 {
     4     int dis[100005],n,m,total_dis=0;
     5     memset(dis, 0, (100005*sizeof(int)));
     6     scanf("%d", &n);
     7     for (int i = 0; i < n; i++)
     8     {
     9         scanf("%d", &dis[i]);
    10         total_dis += dis[i];
    11     }
    12     scanf("%d", &m);
    13     for (int i = 0; i < m; i++) {
    14         int prenum, lastnum,nextdis=0;
    15         scanf("%d%d", &prenum, &lastnum);
    16         if (prenum > lastnum) { int temp = prenum;prenum = lastnum;lastnum = temp; }
    17         
    18         for (int j = prenum - 1;j < lastnum - 1;j++)
    19             nextdis += dis[j];
    20         if (total_dis - nextdis >= nextdis) printf("%d
    ", nextdis);
    21         else printf("%d
    ", total_dis-nextdis);
    22     }
    23     return 0;
    24 }

    不过这个代码交上去,还是有一个运行超时。牛客PATOJ的全部通过,但PAT官网OJ最后一个超时。

    主要原因出在我每次计算最短距离都要遍历数组,大概相当于O(m*n)的复杂度。运行时间太长。

    然后我就求助教材了,发现可以给数组保存为第i个元素是第i个点到第i个点的距离,然后求两个点a,b之间的距离就可以直接dis[b]-dis[a]了。(其中a<b,否则交换)

    这样的话就输入的时候遍历n次,找最短距离的时候遍历m次就行了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int main()
     5 {
     6     int dis[100005], n, m, total_dis = 0;
     7     scanf("%d", &n);
     8     for (int i = 0; i < n; i++)
     9     {
    10         int temp;
    11         scanf("%d", &temp);
    12         dis[i] = total_dis;
    13         total_dis += temp;
    14         //printf("i: %d dis:%d  total:%d
    ", i, dis[i],total_dis);
    15     }
    16     scanf("%d", &m);
    17     for (int i = 0; i < m; i++) {
    18         int prenum, lastnum;
    19         scanf("%d%d", &prenum, &lastnum);
    20         if (prenum > lastnum) swap(prenum, lastnum);
    21         int temp = dis[lastnum-1] - dis[prenum-1];
    22         printf("%d
    ",min(temp,total_dis-temp));
    23     }
    24     return 0;
    25 }

    然后终于通过啦。

    这也学到了一点,拿到题先想想有没有简化的方法,按照最简单的思维去写代码,往往可能运行超时。

    就像这道题最后一种方法,就简化了很多。越简单的题越需要脑子,不要一拿上来就做。

    int main(){int dis[100005],n,m,total_dis=0;memset(dis, 0, (100005*sizeof(int)));scanf("%d", &n);for (int i = 0; i < n; i++){scanf("%d", &dis[i]);total_dis += dis[i];}scanf("%d", &m);for (int i = 0; i < m; i++) {int prenum, lastnum,nextdis=0;scanf("%d%d", &prenum, &lastnum);if (prenum > lastnum) { int temp = prenum;prenum = lastnum;lastnum = temp; }for (int j = prenum - 1;j < lastnum - 1;j++)nextdis += dis[j];if (total_dis - nextdis >= nextdis) printf("%d ", nextdis);else printf("%d ", total_dis-nextdis);}return 0;}

  • 相关阅读:
    Shiro学习(一)总体介绍
    Spring-MVC理解之一:应用上下文webApplicationContext
    现代软件工程 第十四章 【质量保障】 练习与讨论
    rtsp 流媒体服务器,播放器
    ios app 打包
    xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH ​
    Bootstrap日期和时间表单组件
    微信小程序组件action-sheet
    微信小程序组件radio
    微信小程序组件slider
  • 原文地址:https://www.cnblogs.com/albert-yzp/p/9977473.html
Copyright © 2011-2022 走看看