• 双向链表 Boxes in a Line UVA


      首先记录一下对链表的理解,最初看链表是在教材上看的,上面是用结构体, 理解起来还不是很困难,我也以为自己懂了,然而看到紫书上链表用的是数组(UVA11988),真的是。。到最后把他的代码背下来了都还是有点晕(/(ㄒoㄒ)/~~),那个时候做题有点匆忙,也就没深究,不过后面那道(也就是这道)也就没再写了,差不多隔了一个月吧,有那么一点点感觉就是这次没看代码自己写过一遍后。

      单向每一个结构体有两个元素(或者更多),其中一个是下一个元素的地址,其他的是他本身有的东西,在这道题中,1 2 3 4 5, 2的next是3所在的地址,若操作要求把5放到3的左边,即1 2 5 3 4,这个时候2的next就是5所在的地址,双向其实就是加了个东西,就叫做before和after吧,在这个变化所要改的是2的after(3->5), 3的before(2->5), 4的after(5->NULL), 5的before(4->2)和after(NULL->3),看起来比数组要复杂一点,可是在100000这种范围里面,这样的一个指令如果用数组则要改变上万个数字的下标,而链表要改变的只是五六个数字而已。就大大减少了运行时间。这道题书上用的还是环形链表,只是加了个0,这样就不存在head和null,也不用考虑很多临界数据(我一开始用的是直链,以至于末尾数据的考虑占了绝大多数时间和代码量),挺棒的。 

      题意:对于一行按照顺序排列盒子,执行三种操作,command== 1, x 放到 y 的左边;==2, 右边; ==3 交换x, y;==4 全部顺序颠倒

      

      受到一个学长劝告,不要一昧的看别人的代码,如果思路实在想不到可以看看思路,但是编写的过程最好自己完成。

      对于这道题,由于有了一点对链表的理解,所以看到书上说这题需要用双向链表,认为自己可以独立写出来,就没看例题上的代码,用了七八小时,才使自己编写的程序对上了所有的数据(原题样例和ubudge里的样例),不过最后还是超时,没办法还是看了看书上的,发现原来是当command=4的时候我对所有盒子左右都颠倒了,这一步在n=100000的数据时非常的耗时,,,书上讲的inv的方法非常的棒,但是若移植到我的程序里面需要改动的地方实在太多,所以。。。我还是直接看书上的代码,看完后自己敲了一遍,由于自己已经花了这么多的时间去自己理解,所以这一步花的时间不算多。

      书上用的环形双向链表,用的不是结构体而是数组,想想由于同一种数据不是很多,用数组也确实更好,起码代码量特少,敲起来也简便

      最后通过了,不过不知道为什么时间是其他代码的三倍左右, 检查了一下思路确实一样,最后是把书上的代码抄了一遍,才发现原因竟然是。。。我用的是cin而不是scanf(O__O "…),第五章说cin慢我还不知道指什么,现在看来。。。好像是的( ~~~~(>_<)~~~~) 

      最后代码如下(其实没必要,与书上的差不多。。。)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>

    using namespace std;
    int lef[100005], rig[100005];
    void link(int x, int y)
    {
    rig[x] = y; lef[y] = x;
    }
    int main()
    {
    int n, m, kase;
    while(cin >> n >> m)
    {
    for(int i = 1; i <= n; i++)
    {
    lef[i] = i - 1;
    rig[i] = (i + 1) % (n + 1);
    }
    rig[0] = 1; lef[0] = n;
    int op, x, y, inv = 0;
    while(m--)
    {
    scanf("%d", &op);
    if(op == 4) inv = !inv;
    else {
    scanf("%d%d", &x, &y);
    if(op == 3 && lef[x] == y) swap(x, y);
    if(op != 3 && inv) op = 3 - op;
    if(op == 1 && lef[y] == x) continue;
    if(op == 2 && rig[y] == x) continue;
    int xl = lef[x], xr = rig[x], yl = lef[y], yr = rig[y];
    if(op == 1)
    {
    link(xl, xr); link(yl, x); link(x, y);
    }
    else if(op == 2)
    {
    link(xl, xr); link(y, x); link(x, yr);
    }
    else
    {
    if(rig[x] == y) {link(xl, y); link(y, x); link(x, yr); }
    else {link(xl, y); link(y, xr); link(yl, x); link(x, yr); }
    }
    }

    }
    int b = 0;
    long long ans = 0;
    for(int i = 1; i <= n; i++)
    {
    b = rig[b];
    if(i % 2) ans += b;
    }
    if(inv && n % 2 == 0) ans = (long long)n * (n + 1) / 2 - ans;
    printf("Case %d: %lld ", ++kase, ans);
    }
    return 0;
    }

      做题反思:最大的收获就是觉得学长讲的挺有道理的,自己摸索的时间久是久了点,不过对于链表的理解却是深刻了许多,而且如果自己不写一遍,小错误不自己犯一遍,根本无法知道,比如这道题一开始写的时候,调试花很长时间的原因主要是对于一些特殊数据,临界数据的处理没有充分考虑,而且自己一开始用的是直链,少考虑的很多错误暴露了自己巨大的缺陷,也能督促自己以后要多留意这方面。还有一点,速度还是太慢了T_T.

    print “ 欢迎来到渣小狼的博客,这既是博客,也是日记,里面记录了小狼的学习经历还有一些小狼的见解,非常希望每一个来到这里的人能够留下只言片语,更加的希望留下的是对于小狼的不足的补充,谢谢(*^__^*) 嘻嘻……”
  • 相关阅读:
    Python抓取妹子图,内含福利
    我是如何通过一部动漫学习英语的?
    SqlServer,Oracle,db2,MySql查询表索引
    cmd命令大全
    资源推荐:PPT快闪资源合集附配套字体下载
    安卓抖音全球地区版
    tomcat的Server.xml详解和Host的配置
    Java总结篇系列:Java多线程(三)
    Java总结篇系列:Java多线程(二)
    Java总结篇系列:Java多线程(一)
  • 原文地址:https://www.cnblogs.com/wolf-yasen/p/6329536.html
Copyright © 2020-2023  润新知