算法题1

#include <iostream>
#include <vector>

using std::cout;
using std::cin;
using std::endl;
using std::vector;

size_t MinInOneLine(const vector<vector<int> > & vec);
size_t MinInOneDirection(vector<vector<int> > & vec);
size_t MinDrawLine(const size_t N);

int main()
{
	size_t S = 0;
	size_t N = 0;
	cin >> S;

	for (size_t index = 0; index < S; ++index)
	{
		cin >> N;
		cout << MinDrawLine(N) << endl;
	}

	return 0;
}

size_t MinDrawLine(const size_t N)
{
	if (N < 2) return N;

	int x0 = 0;
	int y0 = 0;
	int x1 = 0;
	int y1 = 0;

	vector<vector<int> > vecType1; // x
	vector<vector<int> > vecType2; // y
	vector<vector<int> > vecType3; // 45
	vector<vector<int> > vecType4; // -45

	for (size_t index = 0; index < N; ++index)
	{
		cin >> x0 >> y0 >> x1 >> y1;

		vector<int> vecTemp;
		vecTemp.push_back(x0);
		vecTemp.push_back(y0);
		vecTemp.push_back(x1);
		vecTemp.push_back(y1);

		// divide into four type
		if (y0 == y1) vecType1.push_back(vecTemp);  // x
		else if (x0 == x1) // y
		{
			vecTemp[0] = vecTemp[1];
			vecTemp[2] = vecTemp[3];
			vecType2.push_back(vecTemp);
		}
		else if ((y1 - y0) / (x1 - x0) > 0) vecType3.push_back(vecTemp); // 45
		else vecType4.push_back(vecTemp); // -45
	}

	return MinInOneDirection(vecType1) + MinInOneDirection(vecType2) + MinInOneDirection(vecType3) + MinInOneDirection(vecType4);
}

size_t MinInOneDirection(vector<vector<int> > & vec)
{
	if (vec.size() < 2) return vec.size();

	size_t nRet = 0;
	bool * pbFlag = new bool[vec.size()];
	for (int i = 0; i < vec.size(); ++i) pbFlag[i] = false;

	// divide into different lines
	for (int i = 0; i < vec.size(); ++i)
	{
		if (pbFlag[i] == true) continue;

		vector<vector<int> > vecTemp;
		vecTemp.push_back(vec[i]);
		for (int j = i + 1; j < vec.size(); ++j)
		{
			bool i = pbFlag[j];
			if (pbFlag[j] == false && vec[j][0] != vec[i][0] && (vec[j][1] - vec[i][1]) / (vec[j][0] - vec[i][0]) == (vec[i][3] - vec[i][1]) / (vec[i][2] - vec[i][0]))
			{
				vecTemp.push_back(vec[j]);
				pbFlag[j] = true;
			}
		}
		nRet += MinInOneLine(vecTemp);
	}

	delete[] pbFlag;
	return nRet;
}

size_t MinInOneLine(const vector<vector<int> > & vec)
{
	if (vec.size() == 0) return 0;
	if (vec.size() == 1) return 1;

	size_t nRet = 1;

	// make a hash table of [nMin, nMax]
	int nMin = 0x7fffffff;
	int nMax = 0x80000000;
	for (int index = 0; index < vec.size(); ++index)
	{
		nMin = vec[index][0] < nMin ? vec[index][0] : nMin;
		nMin = vec[index][2] < nMin ? vec[index][2] : nMin;
		nMax = vec[index][0] > nMax ? vec[index][0] : nMax;
		nMax = vec[index][2] > nMax ? vec[index][2] : nMax;
	}
	bool * pbHash = new bool[nMax - nMin + 1];
	for (int index = 0; index <= nMax - nMin; ++index) pbHash[index] = false;

	// map each drawline into x zone
	int nBegin = 0;
	int nEnd = 0;
	for (int index = 0; index < vec.size(); ++index)
	{
		nBegin = vec[index][0] < vec[index][2] ? vec[index][0] : vec[index][2];
		nEnd = vec[index][0] == nBegin ? vec[index][2] : vec[index][0];

		for (int j = nBegin; j <= nEnd; ++j) pbHash[j - nMin] = true;
	}

	// count min drawline in one line
	bool flag = false;
	for (int index = nMin; index <= nMax; ++index)
	{
		if (flag == true)
		{
			if (pbHash[index - nMin] == true)
			{
				nRet++;
				flag = false;
			}
			continue;
		}
		if (flag == false && pbHash[index - nMin] == false) flag == true;
	}

	delete[] pbHash;
	return nRet;
}

  

时间: 2024-10-13 11:52:24

算法题1的相关文章

笔试算法题(09):查找指定和值的两个数 &amp; 构造BST镜像树

出题:输入一个已经升序排序的数组和一个数字:要求在数组中查找两个数,这两个数的和正好等于输入的那个数字,输出任意一对数字就可以,要求时间复杂度是O(n): 分析:对于升序排序的数组{-i-j-k-m--},只有可能是i+m=j+k(j和k可能是同一个数),所以可以从两边往中间收缩而忽视其他交叉相加的情况: 解题: 1 void FindSumFactor(int *array, int length, int sum) { 2 int left=0, right=length-1; 3 whil

笔试算法题(08):输出倒数第K个节点

出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: 1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* FindLastKth(Node *head, int k) { 6 if(head==NULL) { 7 printf("\nhead is NULL\n"); 8 exit(0); 9 } 10 Nod

笔试算法题(07):还原后序遍历数组 &amp; 半翻转英文句段

出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历): 分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树): 解题: 1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 ==

java基础算法题

为了提高自己的代码能力和算法能力,我决定每天学习一道算法题,吸收前辈思想. [程序1] TestRabbit.java 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子数量的规律为数列:1,1,2,3,5,8,13.....其实就是斐波那契数列  使用递归就可以实现 1 /** 2 * 兔子问题 3 * 2016/5/9 4 * 斐波那契数列求值 5 *题目:古典问题:有一对兔子,

ios 算法题

1兔子算法题 兔子可以跳一步2步或者3步,问跳到100有多少种跳法? // 兔子可以跳一步2步或者3步 // 问跳到100有几种跳法 /* 分析1 两个变量,X*2+Y*3=100. X最大为50,X最小为2 Y最大为32.最小为0 分析2 某个情景分析:假设X=35,Y为10时, 虽然知道了数量,但是兔子的35小步,和10大步的顺序是怎样的? 应为组合-> 45个节点中,选择10个放三步的.那就是简单的C(45 10).变成阶乘,就解得出来. */ double temp=0.0f; for

[solution]腾讯TEG_计算广告组_算法题

度娘笔试归来,题目实打实的,感觉真心不易,上百号人就抢那么几个坑......只恨自己平时积累太少啊~ 故曝一道鹅厂面试用的算法题(当时我就死在了这题上),来为度娘家攒一下RP~ 题目: 对于长度为N的一个无序的数组a[1..N],请将a进行排序,要求所有正数都排在0之前,所有负数都排在0之后(如果没有0,则所有正数排在负数前) 要求时间复杂度O(N),空间复杂度O(1) 题目不难,但给思考的时间很短,大约不到5分钟吧.当时脑子比较短路,于是只给出了O(n) O(n)复杂度的算法,然后就被面试官挂

算法题——翻转链表中的一段

题目:给出一个链表中的两个指针p1和p2,将其之间的结点翻转. 思路:可以通过交换结点内的值来实现结点的翻转,空间为O(N):如果要求不能交换值,那么仅凭p1和p2是无法翻转的,只能交换两个指针之间的链表. 代码: 交换值: 1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 }; 6 7 void reverseNodes(ListNode *p1, ListNode *p2) { 8 if ( p1 == NULL || p2 == NU

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

一天一道算法题--6.25--无定义

感谢微信平台---一天一道算法题--每天多一点进步---- 其实今天我接下去补上的几题都来自---待字闺中 所以我就原封不动的将它的题目与分析搬过来了 原题 给定一个数组,我们可以找到两个不相交的.并且是连续的子数组A和B,A中的数字和为sum(A), B中的元素和为sum(B).找到这样的A和B,满足sum(A) - sum(B)的绝对值是最大的. 例如:[2, -1 -2, 1, -4, 2, 8]划分为A=[-1, -2, 1, -4], B=[2, 8], 最大的值为16 分析 如果没有