Sorting It All Out(关系判断排序算法)

今天的题目是英文,如果懒得看的可以直接看下面我凭借过了大学英语32级的水平的精简翻译。

Description(题目描述)

An ascending sorted sequence of distinct values is one in which some form of aless-than operator is used to order the elements from smallest to largest. Forexample, the sorted sequence A, B, C, D implies that A < B, B < C and C< D. in this problem, we will
give you a set of relations of the form A <B and ask you to determine whether a sorted order has been specified or not.

Input

Input consists of multiple problem instances. Each instance starts with a linecontaining two positive integers n and m. the first value indicated the numberof objects to sort, where 2 <= n <= 26. The objects to be sorted will bethe first n characters of the
uppercase alphabet. The second value m indicatesthe number of relations of the form A < B which will be given in thisproblem instance. Next will be m lines, each containing one such relationconsisting of three characters: an uppercase letter, the character"<"
and a second uppercase letter. No letter will be outside therange of the first n letters of the alphabet. Values of n = m = 0 indicate endof input.

Output

For each problem instance, output consists of one line. This line should be oneof the following three:

Sorted sequence determined after xxx relations: yyy...y.

Sorted sequence cannot be determined.

Inconsistency found after xxx relations.

where xxx is the number of relations processed at the time either a sortedsequence is determined or an inconsistency is found, whichever comes first, andyyy...y is the sorted, ascending sequence.

输入样例

4 6

A<B

A<C

B<C

C<D

B<D

A<B

3 2

A<B

B<A

26 1

A<Z

0 0

输出样例

Sorted sequence determined after 4 relations: ABCD.

Inconsistency found after 2 relations.

Sorted sequence cannot be determined.

题目出处:

http://www.programfan.com/acm/show.asp?qid=114

题目翻译:

会给出两个数字,前面一个数字N表示有几个待排序元素,后面一个数字M表示有几个关系。

输出三种情况:

1.      第M对关系能得出个数字的唯一排序:12345…

2.      第X对序列与之前的X-1对序列出现矛盾

3.      排序序列不唯一

问题分析:

判断三种输出结果的条件如下

1.      关系加入关系集合

2.      如果加入关系时发生矛盾,则矛盾,第几个关系出现矛盾也很好判断。

3.      从最小元素开始遍历,如果最长路径包含所有元素,则序列唯一

现在的问题就是:如何整合呢?

运用某种集合S存储已排序序列(只需要表示相对关系,不需要表示绝对关系),每次添加一个新关系进入集合S

虽然说题设假设只有小于号,但是即使没有这样的提设,我们也应该把符号统一,这样编程会很方便。

对于这种元素之间有先后关系,且可能存在多个直接后继的数据结构(因为本题存在不能确定的情况,在不能确定的情况时后继和前驱都可能是多个),我们可以用AOV网来存储这种集合关系(类似的思路还有这道题:http://blog.csdn.net/ganze_12345/article/details/42780275)。(当然,用树也可以,但是如果用树会有大量的重复节点的副本存在,这是没必要的。)同时用一个一维26位的数组来计入已经加入集合的元素值。

这样一来:如果新的加入关系的两个元素都在AVO网中,一定会出现矛盾或者已经相关。

大者如果在小者的大者集合中,则是一个已经存在的关系,如果不是则一定矛盾。者是如果新加入的关系中有含未加入的元素,则一定是一种新关系,把这种新关系加入AOV网。

这样一来可以开始编程了….

#include <iostream>
#include <set>
#include <stack>
#include <limits>
#include <memory>
#include <algorithm>
#include <iterator>
#include <string>
#include <list>
using namespace std;

class Node;
class Relation;

typedef shared_ptr<Node> NodePtr;
typedef shared_ptr<Relation> RelationPtr;

class Node
{//节点
	friend ostream& operator << (ostream &, const Node &);
	friend class Relation;
private:
	char value;
public:
	enum
	{
		MINVALUE = CHAR_MIN,//标志最小节点值
		OFFSET = 'A'		//CHAR的偏移量
	};
	Node() :value(MINVALUE){}
	Node(char v) :value(v){}
	bool operator == (const Node& n)
	{
		return n.value == value;
	}
	static bool InputCheck(char v)
	{
		return v >= 'A' && v <= 'Z';
	}
};
ostream& operator << (ostream &out,const Node &n)
{//重载标准输出流
	if (n.value)
		return out << n.value;
	return out;
}
class Relation
{//关系
	friend class RelationSet;
private:
	NodePtr less;	//当前元素值
	set<RelationPtr> moreSet;//大者的集合
public:
	//参数l表示小者,参数m表示大者
	Relation(NodePtr l) :less(l)
	{}
	bool IsInMoreSet(RelationPtr m)
	{
		bool isIn = false;
		if (find(moreSet.begin(), moreSet.end(), m) != moreSet.end())//在集合中
			return true;
		for (auto itr : moreSet)
		{
			isIn = isIn || itr->IsInMoreSet(m);
		}
		return isIn;
	}
	bool CheckNumber(int n, stack<char> & record, int depth = 0)
	{//校验,n来标记当前比较到的节点的大小位置,record来记录路径
		bool isEqual = false;
		if (depth == n)
		{//最长路径
			record.push(this->less->value);
			return true;
		}
		for (auto itr : moreSet)
		{
			if (isEqual = (isEqual || itr->CheckNumber(n, record, depth + 1)))
			{//在最长路劲上
				if (depth)
				{//第一个节点是为了编程方便,不入栈
					record.push(this->less->value);
					break;
				}
			}
		}
		return isEqual;

	}
	static bool InputChech(char sign)
	{
		return sign == '<' || sign == '>';
	}
	static bool isLessThanSign(char sign)
	{
		return sign == '<';
	}
};

class RelationSet
{//关系集合
	static const char * const resultSet[];//结果集合
	enum
	{
		CERTAIN,//确定序列
		INCONSISTENCY,//结果是矛盾的
		UNCERTAIN//不确定
	};
	static list<string> resultBuffer;//结果集合的缓存
private:
	bool haveChecked;//已经得出结果了
	pair<RelationPtr,bool> * record;//记录已经加入的元素的,前者记录元素位置,后者记录元素是否已经加入
	int elementsNumber;//元素个数
	int relationsNumber;//关系个数
	int relationJoin;//已加入关系数量
	Relation minNode;//最小节点
	string result;//本关系集的结果

	pair<RelationPtr, RelationPtr > Parse(const string &expression)
	{//语义分析
		if (expression.length() == 3)
		{
			char l = expression[0];
			char s = expression[1];
			char m = expression[2];
			if (Node::InputCheck(l) && Node::InputCheck(m) && Relation::InputChech(s))
			{
				if (!Relation::isLessThanSign(s))
					swap(l, m);//所有的符号都调整为小于号
				if (!record[l - Node::OFFSET].second)//节点未经添加
				{
					record[l - Node::OFFSET].first = RelationPtr(new Relation(NodePtr(new Node(l))));
					record[l - Node::OFFSET].second = true;
				}
				if (!record[m - Node::OFFSET].second)//节点未经添加
				{
					record[m - Node::OFFSET].first = RelationPtr(new Relation(NodePtr(new Node(m))));
					record[m - Node::OFFSET].second = true;
				}
				RelationPtr lPtr = record[l - Node::OFFSET].first, mPtr = record[m - Node::OFFSET].first;
				return pair<RelationPtr, RelationPtr >(lPtr,mPtr);
			}
			throw "The of content expression is error";
		}
		throw "The length of expression is error";
	}
public:
	RelationSet(int en,int rn)
		:elementsNumber(en), relationsNumber(rn), minNode(NodePtr(new Node())), relationJoin(0), haveChecked(false)
	{
		record = new pair<RelationPtr, bool>[en];
		memset(record, 0, en);
	}
	void JoinRelation(const string &expression)
	{
		if (++relationJoin > relationsNumber)
			throw "the number of relations is error";

		auto elementPair = RelationSet::Parse(expression);
		if (elementPair.second->IsInMoreSet(elementPair.first))
		{//如果小元素在大元素的子集中,则一定矛盾
			haveChecked = true;
			char r[100];
			sprintf_s(r, resultSet[RelationSet::INCONSISTENCY], relationJoin);
			result = r;
			return;
		}

		if (haveChecked)//已经得出结果了
			return;
		//以上两个判断有先后顺序的原因是在得出唯一序列之后,新加入的关系也有可能导致矛盾,如果这样还是需要否定之前的判断

		if (find(minNode.moreSet.begin(), minNode.moreSet.end(), elementPair.first) == minNode.moreSet.end())//小元素未加入
		{
			minNode.moreSet.insert(elementPair.first);
		}
		if (find(minNode.moreSet.begin(), minNode.moreSet.end(), elementPair.second) == minNode.moreSet.end())//大元素未加入
		{
			minNode.moreSet.insert(elementPair.second);
		}
		elementPair.first->moreSet.insert(elementPair.second);
		GetResult();//因为需要判断是第几个关系得出的结果,所以每次加入一对结果都判断一次。
	}

	const string& GetResult()
	{
		if (!haveChecked)
		{//还没有得出结果
			stack<char> sequence;//序列集合,如果要依据这个序列输出
			if (minNode.CheckNumber(elementsNumber,sequence))
			{
				haveChecked = true;
				char r[100];
				sprintf_s(r, resultSet[RelationSet::CERTAIN], relationJoin);
				result = r;
				while (!sequence.empty())
				{
					result += sequence.top();
					sequence.pop();
				}
				result += '.';
			}
			else
			{
				result = resultSet[RelationSet::UNCERTAIN];
			}
		}
		return result;
	}

	static void InputSet()
	{//集合输入
		int m = 0, n = 0;

		while (scanf_s("%d%d",&m,&n) != EOF && m && n)
		{//如果m或者n为0,则退出
			RelationSet temp(m, n);
			for (; n > 0; --n)
			{
				string expression;
				cin >> expression;
				temp.JoinRelation(expression);
			}
			RelationSet::resultBuffer.push_back(temp.GetResult());
		}
	}

	static void OutPut()
	{
		copy(resultBuffer.begin(), resultBuffer.end(), ostream_iterator<string>(cout, "\n"));
		resultBuffer.clear();//输出完清空缓存
	}

	~RelationSet()
	{
		delete[] record;
	}
};

const char * const RelationSet::resultSet[] = {
	"Sorted sequence determined after %d relations:",
	"Inconsistency found after %d relations.",
	"Sorted sequence cannot be determined."
};
list<string> RelationSet::resultBuffer;
int _tmain(int argc, _TCHAR* argv[])
{
	RelationSet::InputSet();
	RelationSet::OutPut();

	return 0;
}

如何过英语32级?考八次四级就行了....

时间: 2024-10-29 19:53:29

Sorting It All Out(关系判断排序算法)的相关文章

POJ1094 Sorting It All Out(拓扑排序)每输入条关系判断一次

Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 29182   Accepted: 10109 Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from s

ZZUOJ 1199 大小关系(拓扑排序,两种方法_判断入度和dfs回路判断)

1 /* 2 这道题如果按照度为0的节点来判断的时候,将度为0的节点和其相连的节点(度数并减去1) 3 从图中去掉,如果度为0的节点的个数为0个但是图中的节点没有都去掉的 时候那么说明 4 出现了回路!用这种方法必须将重边去除掉! 5 6 所以推荐用dfs方式进行判断!这种方式还是比较直观的! 7 */ 8 #include<iostream> 9 #include<cstring> 10 #include<cstdio> 11 #include<algorith

Collection of algorithm for sorting. 常见排序算法集(一)

Collection of algorithm for sorting (part one) 选择排序--Selection sort 可能你会觉得奇怪,为什么用结构体传参? 那是一层封装,我在面向对象的思想来写 : ) 对已一个数组,不管怎么操作,都不能越界. C语言 不会自动检查数组越界.这个时候程序员就应该负起责任来. 数组的边界成为数组必不可少的信息,此时可以把array当作一个对象来看,即此时的element. 我们排序的对象可能会变,比方说从int类型变到char类型,这时候我们仅仅

链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述

关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学习过算法的系统性的课程,现在还是处于不断摸索的阶段,好多算法题目根本就没有什么思路,导致自己对好多题目都很是头疼,就算是自己做过的一些算法的题目,再次遇到也还是不一定会做出来,他给出的建议就是,看懂别人的程序,然后自己去敲,一定会出错,然后调试,有错误接着调试,一直到没有错误为止,并且要时常的去复习

经典排序算法 - 耐心排序Patience Sorting

经典排序算法 - 耐心排序Patience Sorting 这个排序的关键在建桶和入桶规则上 建桶规则:如果没有桶,新建一个桶;如果不符合入桶规则那么新建一个桶 入桶规则:只要比桶里最上边的数字小即可入桶,如果有多个桶可入,那么按照从左到右的顺序入桶即可 举个例子,待排数组[6 4 5 1 8 7 2 3] 第一步,取数字6出来,此时一个桶没有,根据建桶规则1新建桶,将把自己放进去,为了表述方便该桶命名为桶1或者1号桶 第二步,取数字4出来,由于4符合桶1的入桶规则,所以入桶1,并放置在6上边,

查找与排序算法(Searching adn Sorting)

1,查找算法 常用的查找算法包括顺序查找,二分查找和哈希查找. 1.1 顺序查找(Sequential search) 顺序查找: 依次遍历列表中每一个元素,查看是否为目标元素.python实现代码如下: #无序列表 def sequentialSearch(alist,item): found = False pos=0 while not found and pos<len(alist): if alist[pos]==item: found=True else: pos = pos+1 r

排序算法(sorting)

对COMP20003中排序部分进行总结,图片来自COMP20003 有部分内容来自http://www.cnblogs.com/eniac12/p/5329396.html 演示动画:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html 概念: stable sort: 相同的值排序后相对顺序不变. Comparison-based sorting is Ω(nlogn). Hash function --- 用数对

普林斯顿大学算法课 Algorithm Part I Week 3 排序算法复杂度 Sorting Complexity

计算复杂度(Computational complexity):用于研究解决特定问题X的算法效率的框架 计算模型(Model of computation):可允许的操作(Allowable operations) 成本模型(Cost model):操作数(Operation counts) 上界(Upper bound):最多的成本 下界(Lower bound):最少的成本 最优算法(Optimal algorithm):最有可能性的成本的算法(Algorithm with best pos

排序算法总结及面试题

排序算法总览 排序大的分类可以分为两种:内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.下面讲的排序都是属于内排序.内排序有可以分为以下几类: (1).插入排序:直接插入排序.二分法插入排序.希尔排序. (2).选择排序:简单选择排序.堆排序. (3).交换排序:冒泡排序.快速排序. (4).归并排序 (5).线性时间排序:计数排序.基数排序.桶排序 算法复杂度以及稳定性分析 外排序 外排序(External sorting)是指能够处理