본문 바로가기
C++/과제

[백트레킹] 점들을 연결했을 때 최소 거리 구하기

by 2744m 2018. 10. 9.

마우스로 10개 이하의 점을 임의로 찍어서 모든 점들을 연결했을 때 가장 짧은거리를 그려보자.


 <소스코드>


#include<opencv2/opencv.hpp>
#include <iostream>
#include <random>
#include <time.h>
#include <stack>


#define nonMouse "Non MouseEvent"
#define useMouse "Mouse Event"

using namespace std;
using namespace cv;
struct temp { int x, y; }pt[10], temp2;
stack<temp>S, MIN_D;
int visit[10];
temp Min_pt[10];
int Min_dis = 2147438646;
int dot;
int temp_distance;

void draw_line(int s, int n) { //n은 그려야할 남은 선 개수 s는 현재 점
	if (n == 0) {
		temp2.x = pt[s].x;
		temp2.y = pt[s].y;
		S.push(temp2);
		if (temp_distance <= Min_dis) {
			Min_dis = temp_distance;
			MIN_D = S;
		}
		S.pop();
		return;
	}
	else {
		for (int i = 0; i < dot; i++) { //i는 다음점
			if (visit[i] == 0) {
				temp2.x = pt[s].x;
				temp2.y = pt[s].y;
				S.push(temp2);
				int stoi = (pt[s].x - pt[i].x)*(pt[s].x - pt[i].x) + (pt[s].y - pt[i].y)*(pt[s].y - pt[i].y); //거리 구할 때 비교만 할 것이므로 굳이 루트처리 안해줌
				temp_distance = temp_distance + stoi;
				visit[i] = 1;
				draw_line(i, n - 1);
				visit[i] = 0;
				temp_distance = temp_distance - stoi;
				S.pop();

			}
		}
	}
}

void onMouseEvent(int event, int x, int y, int flags, void * dstImage) {
	Mat mouseImage = *(Mat*)dstImage;

		switch (event) {
			//클릭이벤트
		case CV_EVENT_LBUTTONDOWN:
			cout << Point(x, y) << endl;
			pt[dot].x = x;
			pt[dot].y = y;
			Point pin(x, y);
			circle(mouseImage, pin, 1.5, Scalar(0, 0, 255), 2); // 좌표를 시각화
			dot++;
			cout << "점 :" << dot << "개 입력" << "\n";
			
		
			
			break;
		}
	
		imshow(useMouse, mouseImage);
	}

int main() {
	srand(time(NULL));
	Mat dstImage(500, 500, CV_8UC3, Scalar(255, 255, 255));
	Mat srcIamge = dstImage;
	if (srcIamge.empty()) {
		return -1;
	}

	//imshow(nonMouse, srcIamge);
	imshow(useMouse, srcIamge);
	setMouseCallback(useMouse, onMouseEvent, (void*)&srcIamge);
	int inkey;
	while(1) {
		inkey = waitKey();
		if (inkey == 13) {
			for (int i = 0; i < dot; i++) {
				visit[i] = 1;
				draw_line(i, dot - 1); // 선의 개수 = 점 - 1
				visit[i] = 0;
			}

			while (1) {
				Point pin1(MIN_D.top().x, MIN_D.top().y);
				MIN_D.pop();
				if (!MIN_D.empty()) {
					Point pin2(MIN_D.top().x, MIN_D.top().y);
					line(dstImage, pin1, pin2, Scalar(0, 0, 0), 1);
				}
				else break;
			}
	
			break;
		}
		cout <<"엔터"<< endl;
	}
	waitKey();
	return 0;
}


점을 찍고 엔터를 치면 최소 거리의 길을 그려준다.

기존에 실행시 랜덤으로 2~10개의 점을 찍어서 그려주던 코드에서 마우스 이벤트만 추가한 것이라 코드가 지저분하다.


<실행결과>


'C++ > 과제' 카테고리의 다른 글

K-d tree vs Brute-force 탐색 속도비교  (0) 2019.06.07

댓글