IPPP (Institute of Penniless Peasent-Programmer) Fellow

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::
  77 随笔 :: 0 文章 :: 439 评论 :: 0 引用



A typical windowing system on a computer will provide a number of icons on the screen as well as some defined regions. When the mouse button is clicked, the system has to determine where the cursor is and what is being selected. For this problem we assume that a mouse click in (or on the border of) a region selects that region, otherwise it selects the closest visible icon (or icons in the case of a tie).

Consider the following screen:




A mouse click at 'a' will select region A. A mouse click at 'b' will select icon 1. A mouse click at 'c' will select icons 6 and 7. A mouse click at 'd' is ambiguous. The ambiguity is resolved by assuming that one region is in front of another. In the data files, later regions can be assumed to be in front of earlier regions. Since regions are labelled in order of appearance (see later) 'd' will select C. Note that regions always overlap icons so that obscured icons need not be considered and that the origin (0,0) is at the top left corner.
鼠标点在“a”处将选中区域A,点在“b”处将选中图标1,点在“c”处将选中图标6和7,而点在'd'处则会产生一个歧意。当产生歧意时应选中较为靠前的一个区域。在输入的数据中,后给出的区域应被视为在先给出的区域之前。注意,区域将会覆盖相应位置的所有图标,被覆盖的图应被忽略。坐标原点(0, 0)位于左下角。

Write a program that will read in a series of region and icon definitions followed by a series of mouse clicks and return the selected items. Coordinates will be given as pairs of integers in the range 0..499 and you can assume that all icons and regions lie wholly within the screen. Your program must number all icons (even invisible ones) in the order of arrival starting from 1 and label regions alphabetically in the order of arrival starting from 'A'.



Input will consist of a series of lines. Each line will identify the type of data: I for icon, R for region and M for mouse click. There will be no separation between the specification part and the event part, however no icon or region specifications will follow the first mouse click. An I will be followed by the coordinates of the centre of the icon, R will be followed by the coordinates of the top left and bottom right corners respectively and M will be followed by the coordinates of the cursor at the time of the click. There will always be at least one visible icon and never more than 25 regions and 50 icons. The entire file will be terminated by a line consisting of a single #.



Output will consist of one line for each mouse click, containing the selection(s) for that click. Regions will be identified by their single character identifier, icon numbers will be written out right justified in a field of width 3, and where there is more than one icon number they will appear in increasing numerical order.


Sample input

I       216     28
R       22      19      170     102
I       40      150
I       96      138
I       36      193
R       305     13      425     103
I       191     184
I       387     200
R       266     63      370     140
I       419     134
I       170     102
M       50      50
M       236     30
M       403     167
M       330     83


Sample output

  6  7






#include <iomanip>
#include <iostream>
#include <iterator>
#include <deque>
using namespace std;
struct POINT {int x; int y;};
struct RECT {POINT tl; POINT br;};
bool PointInRect(const POINT &pt, const RECT &rc) {
	return (pt.x >= rc.tl.x && pt.x <= rc.br.x &&
		pt.y >= rc.tl.y && pt.y <= rc.br.y);
int PointDistance(const POINT &pt1, const POINT &pt2) {
	POINT Vec = {pt2.x - pt1.x, pt2.y - pt1.y};
	return (Vec.x * Vec.x + Vec.y * Vec.y);
int main(void) {
	deque<POINT> Icons, Clicks;
	deque<RECT> Rects;
	for (char Tag = 0; cin >> Tag && Tag != '#'; ) {
		RECT rc;
		switch (Tag) {
		case 'I': //输入图标数据
			cin >> rc.tl.x >> rc.tl.y;
		case 'R': //输入矩形数据
			cin >> rc.tl.x >> rc.tl.y >> rc.br.x >> rc.br.y;
			if (rc.br.x < rc.tl.x) *(int*)0 = 0;
			if (rc.br.y < rc.tl.y) *(int*)0 = 0;
			if (Rects.size() > 26) *(int*)0 = 0;
		case 'M': //输入鼠标点击事件(坐标)
			cin >> rc.tl.x >> rc.tl.y;
	deque<POINT>::iterator iIcon, iClick;
	deque<RECT>::iterator iRect;
	for (iIcon = Icons.begin(); iIcon != Icons.end(); ++iIcon) {
		for (iRect = Rects.begin(); iRect != Rects.end(); ++iRect) {
			if (PointInRect(*iIcon, *iRect)) {
				iIcon->x = 10000; //将该图标移至无穷远处,即将其忽略
				iIcon->y = 10000; //不能删除,以免影响后面图标的编号
	for (iClick = Clicks.begin(); iClick != Clicks.end(); ++iClick) {
		deque<RECT>::reverse_iterator riRect;
		for (riRect = Rects.rbegin(); riRect != Rects.rend() &&
			!PointInRect(*iClick, *riRect); ++riRect);
		if (riRect != Rects.rend()) {
			cout << (char)(distance(riRect, Rects.rend()) - 1 + 'A') << endl;
		deque<int> SelIcons(1, 1);
		deque<POINT>::iterator iNear = Icons.begin(), iIcon;
		int nNear = PointDistance(*iClick, *iNear);
		for (iIcon = iNear + 1; iIcon != Icons.end(); ++iIcon) {
			int nDist = PointDistance(*iClick, *iIcon); //计算距离
			if (nDist < nNear) {
				iNear = iIcon;
				nNear = nDist;
				SelIcons.clear(); //清空原先的数组,以新图标代替
				SelIcons.push_back(distance(Icons.begin(), iIcon) + 1);
			else if (nDist == nNear) { //发现同为最短距离的图标则加入数组
				SelIcons.push_back(distance(Icons.begin(), iIcon) + 1);
		deque<int>::iterator iSel;
		for (iSel = SelIcons.begin(); iSel != SelIcons.end(); ++iSel) {
			cout << setw(3) << *iSel;
		cout << endl;
	return 0;
posted on 2010-08-24 19:34 Devymex 阅读(...) 评论(...) 编辑 收藏