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;
}
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;
}
同理可知操作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;
}
这道题很容易想到要构建一个循环链表来确定每个球的相对位置,就是操作比较繁琐,考虑情况较多。
首先要创建节点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;
}
相关文章推荐
- [转]NYOJ-511-移动小球
- [转]NYOJ-511-移动小球
- NYOJ 题目511 移动小球(双向循环链表)
- NYOJ511 移动小球(链表基础题)(链表法+非链表法)
- NYOJ 511 移动小球
- NYOJ 511 移动小球
- NYOJ-511 移动小球【模拟】
- NYOJ 511 - 移动小球 链表版
- nyoj 551 移动小球
- NYOJ-移动小球
- NYOJ 551 移动小球
- sicily 1934. 移动小球
- 更好一种小球组合键移动
- 手指在屏幕上滑动,红色的小球始终跟随手指移动。
- 关于小球自由移动(ASDW)控制方向/easyX/code/
- android从零开始-开发自定义View-跟随手指移动的小球
- js-实现小球的自由移动
- 双向链表nyoj511
- 第二天 移动小球
- 蓝桥杯 - 算法训练 - 移动小球 C语言实现