移动盒子,Boxes in a Line,UVA 12657

题目链接:https://vjudge.net/problem/UVA-12657

题解:这一题的题意是有一行从1到n编号的盒子,按给定的4种指令对盒子进行操作,最后输出奇数位置上的盒子编号的和。解题的数据结构选择双向链表,增加头尾指针用作标注,另外使用一个pos数组记录每个盒子的指针位置,方便直接取得盒子指针。最后根据题意按指令对盒子进行模拟操作。我在这一题中使用的是自己写的指针链表,对指针之间的指向掌握要求比较高。LRJ书中同样给的是数组模拟双向链表,值得参考,也是需要我学习的。

感受:其实解这一题花了我不少的时间的,最开始的时候写出来了一份代码,也是可以解决给定样例的,但是其他例子上有的会有错误,这个错误我检查了好久,后来把之前的写的代码删除重新解题,换了一种结构之后仍然会有同样的问题。我仔细读题之后发现,我对题目的一点理解有误,即ingore this if X is already the left of Y。发现了这个问题之后,直接就AC了。这说明了仔细读懂题目的重要性,每一个细节都得注意到,不然设计和程序就会有很大的问题。另外,在重写的过程中,我意识到了抽象的重要性,在对题目理解加深的基础之后,会将自己的思维融入到解题过程中,这样代码将会变得简短、凝练,但是其他人阅读便需要动一些脑筋了,这也是为什么我读LRJ书中的代码会很困难,感觉他的那些代码都经过了高度的抽象,这是需要我学习的点。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

const int maxn = 1e5 + 10;

struct Num {
	int num;
	Num *pre = NULL;
	Num *next = NULL;
};


Num *pos[maxn];



void create(int n) {

	Num *head = new Num();

	pos[0] = head;

	for (int i = 1; i <= n+1; i++)
	{
		Num *newNum = new Num();

		if (i < n + 1) {
			newNum->num = i;
		}
		else {
			newNum->num = 0;
		}
		

		head->next = newNum;
		newNum->pre = head;

		head = newNum;
		pos[i] = head;
	}
}



void swap_Num(Num *P,Num *Q) {
	if (P->next == Q||P->pre==Q) {
		if (P->pre == Q) {
			Num *t = P;
			P = Q;
			Q = t;
		}
		P->pre->next = Q;
		Q->pre = P->pre;
		P->next = Q->next;
		Q->next->pre = P;
		P->pre = Q;
		Q->next = P;
	}
	else {
		Num *t1 = Q->pre;
		Num *t2 = Q->next;
		P->pre->next = Q;
		Q->pre = P->pre;
		Q->next = P->next;
		P->next->pre = Q;

		P->pre = t1;
		t1->next = P;
		P->next = t2;
		t2->pre = P;
	}
}

void insert_Num(Num *p, Num *q,int flag) {
	if (!flag) {
		p->pre->next = p->next;
		p->next->pre = p->pre;
		q->pre->next = p;
		p->pre = q->pre;
		p->next = q;
		q->pre = p;
	}
	else {
		p->next->pre = p->pre;
		p->pre->next = p->next;
		q->next->pre = p;
		p->next = q->next;
		p->pre = q;
		q->next = p;
	}

}


int main() {

	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	int m, n;
	int c = 0;
	while (cin >> n >> m) {
		
		//cout << n << " " << m << endl;
		memset(pos, NULL, sizeof(pos));
		//create a list of 1...N
		create(n);
		Num *head = pos[0];
		Num *endP = pos[n+1];

		int tp = 0;
		long long int s = 0;
		

		int flag = 0;

		for (int i = 0; i < m; i++)
		{
			int type = 0, X = 0, Y = 0;
			cin >> type;
			if (type != 4) {
				cin >> X >> Y;
			}
			Num *temp = NULL;
			switch (type)
			{
			case 1:
				if (!flag) {
					if (pos[X]->next == pos[Y])continue;
				}
				else {
					if (pos[X]->pre == pos[Y])continue;
				}
				if(pos[X]->next==pos[Y]||pos[X]->pre==pos[Y])
					swap_Num(pos[X], pos[Y]); 
				else{
					insert_Num(pos[X], pos[Y],flag);
				}
				
				break;
			case 2:
				if (!flag) {
					if (pos[X]->pre == pos[Y])continue;
				}
				else {
					if (pos[X]->next == pos[Y])continue;
				}

				if (pos[X]->next == pos[Y] || pos[X]->pre == pos[Y])
					swap_Num(pos[X], pos[Y]);
				else {
					if (!flag) {
						insert_Num(pos[X], pos[Y]->next,flag);
					}
					else {
						insert_Num(pos[X], pos[Y]->pre,flag);
					}
				}
				break;
			case 3:	
				swap_Num(pos[X],pos[Y]);
				break;
			case 4:
				if (flag) {
					flag = 0;
				}
				else {
					flag = 1;
				}
				temp = head;
				head = endP;
				endP = temp;
				break;
			default:
				break;
			}
		}

		s = 0;
		tp = 0;

		if (!flag)
		{
			for (Num *it = head->next; it->next != NULL; it = it->next,tp++)
			{
				if (tp % 2 == 0) {
					s += it->num;
				}
			}
		}
		else {
			for (Num *it = head->pre; it->pre != NULL; it = it->pre, tp++)
			{
				if (tp % 2 == 0) {
					s += it->num;
				}
			}
		}

		cout << "Case " << ++c << ": " << s << endl;

		for (int i = 1; i <= n + 1; i++)delete pos[i];
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/PAN_Andy/article/details/82660478
今日推荐