您的位置:首页 > 其它

NYOJ-511-移动小球

2013-07-23 23:52 127 查看
http://acm.nyist.net/JudgeOnline/problem.php?pid=511

这道题很容易想到要构建一个循环链表来确定每个球的相对位置,就是操作比较繁琐,考虑情况较多。

首先要创建节点Node,每个节点都有一个初始顺序order,指向左边的Node*指针left,何指向右边的Node*指针right。

[cpp]
view plaincopyprint?

struct Node  
{  
    int order;  
    Node *left,*right;  
}node
;  

然后给每个小球附上顺序,并建立和左右的联系。

[cpp]
view plaincopyprint?

void build(int n)  
{  
    int i,order=1;  
    for(i=1;i<n;i++)  
        {  
            node[i].order=i;  
            node[i].right=&node[i+1];  
            node[i+1].left=&node[i];  
        }  
    node[1].left=&node
;  
    node
.right=&node[1];  
    node
.order=n;  
}  
 
然后就是A、B操作,下边叙述一下A操作(将x放在y左边)的实现方法:

1.将x左边节点的right指针指向x的右边节点

2.将x右边节点的left指针指向x的左边节点

3.将x的right指向y节点

4.将x的left指向y左边的节点

5.将y左边节点的right指向x节点

6.将y的left指向x节点

实现代码:

[cpp]
view plaincopyprint?

void A(int x,int y)  
{  
    Node *p=&node[x],*q=&node[y];  
    p->left->right=p->right;  
    p->right->left=p->left;  
    p->left=q->left;  
    p->right=q;  
    q->left->right=p;  
    q->left=p;  
}  
 
由于交换位置仅改变节点的左右指针,并没有改变数组的下标(下标其实与order相同),所以查找球号时直接用下标索引。

同理可知操作B。

完整代码如下:

[cpp]
view plaincopyprint?

#include<stdio.h>   
const int N=10005;  
struct Node  
{  
    int order;  
    Node *left,*right;  
}node
;  
void build(int n)  
{  
    int i,order=1;  
    for(i=1;i<n;i++)  
        {  
            node[i].order=i;  
            node[i].right=&node[i+1];  
            node[i+1].left=&node[i];  
        }  
    node[1].left=&node
;  
    node
.right=&node[1];  
    node
.order=n;  
}  
void A(int x,int y)  
{  
    Node *p=&node[x],*q=&node[y];  
    p->left->right=p->right;  
    p->right->left=p->left;  
    p->left=q->left;  
    p->right=q;  
    q->left->right=p;  
    q->left=p;  
}  
void B(int x,int y)  
{  
    Node *p=&node[x],*q=&node[y];  
    p->left->right=p->right;  
    p->right->left=p->left;  
    p->right=q->right;  
    q->right->left=p;  
    p->left=q;  
    q->right=p;  
}  
int main()  
{  
    int ncase,n,m,i;  
    char cmd;  
    int x,y;  
    scanf("%d",&ncase);  
    while(ncase--)  
    {  
        scanf("%d%d",&n,&m);  
        build(n);  
        while(m--)  
        {  
            scanf("%*c%c%d%d",&cmd,&x,&y);  
            switch(cmd)  
            {  
            case 'A':  
                A(x,y);break;  
            case 'B':  
                B(x,y);break;  
            case 'Q':  
                printf("%d\n",x?node[y].right->order:node[y].left->order);break;  
            }  
        }  
    }  
    return 0;  
}  

其实此题还可以不用链表,对比了一下,时间相差不大,相比而言非链表法更不容易出错。

思路基本一样,直接给出代码:

[cpp]
view plaincopyprint?

   
#include<cstdio>   
const int N=10005;  
struct xyz  
{  
    int prv,nxt;  
}a
;  
void build(int n)  
{  
    int i;  
    for(i=1;i<=n;i++)  
        {  
            a[i].prv=i-1;  
            a[i].nxt=i+1;  
        }  
    a[1].prv=n;  
    a
.nxt=1;  
}  
void A(int x,int y)  
{  
    a[a[x].prv].nxt=a[x].nxt;  
    a[a[x].nxt].prv=a[x].prv;  
    a[x].nxt=y;  
    a[x].prv=a[y].prv;  
    a[a[y].prv].nxt=x;  
    a[y].prv=x;  
}  
void B(int x,int y)  
{  
    a[a[x].prv].nxt=a[x].nxt;  
    a[a[x].nxt].prv=a[x].prv;  
    a[x].nxt=a[y].nxt;  
    a[x].prv=y;  
    a[a[y].nxt].prv=x;  
    a[y].nxt=x;  
}  
int main()  
{  
    int ncase,n,m,i;  
    char cmd;  
    int x,y;  
    scanf("%d",&ncase);  
    while(ncase--)  
    {  
        scanf("%d%d",&n,&m);  
        build(n);  
        while(m--)  
        {  
            scanf("%*c%c%d%d",&cmd,&x,&y);  
            switch(cmd)  
            {  
            case 'A':  
                A(x,y);break;  
            case 'B':  
                B(x,y);break;  
            case 'Q':  
                printf("%d\n",x?a[y].nxt:a[y].prv);break;  
            }  
        }  
    }  
    return 0;  
}  
          
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: