美文网首页
链表---移动盒子(双向链表)

链表---移动盒子(双向链表)

作者: Celia_QAQ | 来源:发表于2019-05-03 18:54 被阅读0次

题目:移动盒子UVa 12657

你有一行盒子,从左到右依次编号为1,2,3,…,n。可以执行以下4种指令:

1 x y:表示把盒子x移动到盒子y的左边(如果x已经在y的左边则忽略此指令)。
2 x y:表示把盒子x移动到盒子y的右边(如果x已经在y的右边则忽略此指令)。
3 x y:表示交换盒子x和y的位置。
4:表示反转整条链。

指令保证合法,即x不等于y。

【输入格式】
输入包含不超过10组数据,每组数据第一行为盒子数n和指令m,以下m行每行包含一条指令。
【输出格式】
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。
【输入样例】
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
【输出样例】
case 1: 12
case 2: 9
case 3: 2500050000


[作者:大1234草]
原文:(https://blog.csdn.net/sinat_38816924/article/details/83514484)


如果是使用数组会超时。
--->Left[i]和Right[i]分别表示编号为i的盒子左边和右边的盒子编号
但是注意了 如果执行了操作4后, 如果操作1 2操作不变的话, 那么操作1就是2,2 就是1(放在左边 + 反转 = 放在右边)

表格(以样例1为例)
输入6个盒子,4条指令

  0 1 2 3 4 5 6
Left [i] 1 0 1 2 3 4 5
Right [i] 6 2 3 4 5 6 0
盒变化
盒子0   1 2 3 4 5 6
1 1 4
盒子1   2 3 1 4 5 6
2 3 5
盒子2   2 1 4 5 3 6
3 1 6
盒子3   2 6 4 5 3 1
4
盒子4   1 3 5 4 6 2

书上代码:

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#define N 100001 
using namespace std;
int Left[N],Right[N];//左右盒子编号 
int n;

int swap(int a,int b){//交换两个值
    int t;
    t=a;
    a=b;
    b=t;
    return a,b;
}
//双向链表的一个比较实用的函数
void link(int l,int r){//连接两个节点 
    Right[l]=r;
    Left[r]=l;
} 

int main()
{
    int m,kase=0;
    //n,m分别为盒子个数和指令条数
    while(scanf("%d%d",&n,&m)==2){//读取两个整形值到n和m
        for(int i=1;i<=n;i++){
            Left[i]=i-1;
            Right[i]=(i+1)%(n+1);
        }
        Right[0]=1;
        Left[0]=n;
        int op,X,Y,inv=0;//inv表示操作4是否执行 
        
        while(m--){
            scanf("%d",&op);
            if(op==4)inv=!inv;//翻转整条链 
            else {
                scanf("%d%d",&X,&Y);
                if(op==3&&Right[Y]==X)swap(X,Y);// !为了转换成同一种情况来处理
                if(op!=3&&inv)op=3-op;
                if(op==1&& X==Left[Y]) continue;
                if(op==2&& X==Right[Y])continue;
                
                int LX=Left[X], RX=Right[X],
                    LY=Left[Y],RY=Right[Y];
                //分类讨论
                if(op==1){
                    link(LX,RX);link(LY,X);link(X,Y);
                }
                else if(op==2){
                    link(LX,RX);link(Y,X);link(X,RY);
                }//X的左右连起来,按照链的顺序来写可能更加清晰
                else if(op==3){
                    if(Right[X]==Y){
                    link(LX,Y);link(Y,X);link(X,RY);}
                    else{
                        link(LX,Y);link(Y,RX);link(LY,X);link(X,RY); } 
                }
            }
        } 
            //奇数位置盒子编号之和
            int b=0;
            long long ans=0;
            for(int i=1;i<=n;i++){
                b=Right[b];//向右推移
                if(i%2==1)ans+=b;
            }
            if(inv && n%2==0) ans=(long long)n*(n+1)/2-ans;//
            printf("case %d: %lld\n",++kase,ans);          //输出 
    }
    return 0; 
}

大佬的代码:
链表解法:::作者:不羡

#include<iostream>  
using namespace std;  
int bigflag = 0;  
struct node {  
    int x;  
    node * next;  
};  
int main() {  
    int n, m;  
    while (cin >> n >> m)  
    {  
        node *head = new node;;  
        head->x = 1;  
        node *temp = head;  
        for (int i = 2; i <= n; i++) {  
            node *p = new node;  
            p->x = i;  
            temp->next = p;  
            temp = p;  
        }  
        temp->next = NULL;  
        int a, b, c;  
        for (int flag = 0; flag < m; flag++) {  
            cin >> a;  
            if (a == 1) {  
                cin >> b >> c;  
                int i, j;  
                node *zz = head;  
                node *hh = head;  
                if (zz->x == b)i = 0;  
                else {  
                    for (i = 1; i < n; i++) {  
                        if (zz->next->x == b)break;  
                        zz == zz->next;  
                    }  
                }//真实位置i+1,要单独考虑在头的情况;  
                if (hh->x == c)j = 0;  
                else {  
                    for (j = 1; j < n; j++) {  
                        if (hh->next->x == c)break;  
                        hh = hh->next;  
                    }  
                }//真实情况j+1;  
                if (i + 1 + 1 != j + 1) {  
                    if (i == 0) {  
                        head = zz->next;  
                        zz->next = hh->next;  
                        hh->next = zz;  
                    }  
                    else {  
                        node *s = new node;  
                        s = zz->next;  
                        zz->next = zz->next->next;  
                        s->next = hh->next;  
                        hh->next = s;  
                    }  
                }  
                node * w = head;  
            }  
            else if (a == 2) {  
                cin >> b >> c;  
                int i, j;  
                node *zz = head;  
                node *hh = head;  
                if (zz->x == b)i = 0;  
                else {  
                    for (i = 1; i < n; i++) {  
                        if (zz->next->x == b)break;  
                        zz == zz->next;  
                    }  
                }//真实位置i+1,要单独考虑在头的情况;  
                for (j = 1; j < n; j++) {  
                    if (hh->x == c)break;  
                    hh = hh->next;  
                }  
                if (i + 1 != j + 1) {  
                    if (i == 0) {  
                        head = zz->next;  
                        zz->next = hh->next;  
                        hh->next = zz;  
                    }  
                    else {  
                        node *p = new node;  
                        p = zz->next;  
                        zz->next = zz->next->next;  
                        p->next = hh->next;  
                        hh->next = p;  
                    }  
                }  
            }  
            else if (a == 3) {  
                cin >> b >> c;  
                node *zz = head;  
                node *hh = head;  
                int i, j;  
                for (i = 1; i < n; i++) {  
                    if (zz->x == b)break;  
                    zz = zz->next;  
                }  
                for (j = 1; j < n; j++) {  
                    if (hh->x == c)break;  
                    hh = hh->next;  
                }  
                int temp;  
                temp = zz->x;  
                zz->x = hh->x;  
                hh->x = temp;  
                node * e = head;  
                int sum = 0;  
            }  
            else if (a == 4) {  
                node *mid = head;  
                node *tail = head->next;  
                for (int i = 1; i < n; i++) {  
                    node *pre = tail->next;  
                    tail->next = mid;  
                    mid = tail;  
                    tail = pre;  
                }  
                node *mm = mid;  
                head = mid;  
            }  
        }  
        node *mark = head;  
        int sum = 0;  
        for (int i = 1; i <= n; i = i + 2) {  
            sum = sum + mark->x;  
            mark = mark->next->next;  
        }  
        cout << "Case "<<bigflag+1<<": "<<sum << endl;  
        bigflag++;  
    }  
    system("pause");  
    return 0;  

相关文章

  • 链表---移动盒子(双向链表)

    题目:移动盒子UVa 12657 你有一行盒子,从左到右依次编号为1,2,3,…,n。可以执行以下4种指令: 1 ...

  • 双向链表&双向循环链表

    链表分为:单链表、单向循环链表、双向链表、双向循环链表本节主要说明:双向链表、双向循环链表 定义结点 一、双向链表...

  • 线性表-双向链表与双向循环链表

    双向链表 双向链表示意图如下: 数据结构定义 创建双向链表 双向链表插入元素 双向链表删除元素 双向链表打印元素 ...

  • 线性表--链式存储结构--双向链表

    双向链表 一、双向链表结构 双向链表结点结构 既然单链表可以有循环链表,那么双向链表当然也可以有。 由于这是双向链...

  • 数据结构与算法之双向链表(3.3)

    目录 双向链表简介双向链表重要方法讲解实战检测双向链表,单向链表性能对比 一 双向链表简介 双向链表-只有一个元素...

  • 双向链表和双向循环链表

    双向链表 线性表-双向链表的结点结构: 带头结点的双向链表: 1.双向链表初始化 2.遍历双向链表 2.双向链表插...

  • day03-双向链表

    双向链表: 单向链表只能单向查找,双向链表可以双向查找。 啥是双向链表? 双向链表可以双向查数据,所以就不存在单向...

  • 双向链表&双向循环链表

    一、双向链表 带有前驱结点、后区节点 双向链表的创建 双向链表插入-逻辑 双向链表删除 删除双向链表指定的元素 二...

  • 9.双向链表DoubleLinkList

    目录:1.双向链表的定义2.双向链表的图解3.双向链表定义操作4.双向链表的实现 1.双向链表的定义 2.双向链表...

  • 双向链表

    双向链表的结构 既然单链表有循环链表,双向链表当然也有双向循环链表,如下图: 问: 双向链表中某个节点p的后继节点...

网友评论

      本文标题:链表---移动盒子(双向链表)

      本文链接:https://www.haomeiwen.com/subject/eilznqtx.html