www.acmicpc.net/problem/17070

 

17070번: 파이프 옮기기 1

유현이가 새 집으로 이사했다. 새 집의 크기는 N×N의 격자판으로 나타낼 수 있고, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 (r, c)로 나타낼 수 있다. 여기서 r은 행의 번호, c는 열의

www.acmicpc.net

- 완전탐색을 문제 조건에 맞게 구현하여 경우의 수를 구하면 되는 간단한 문제이다.

 

- CASE는 방법에 따른 이동을 순열로 구하면 되는데 현재 파이프가 어떻게 놓여져 있는 지 에 따라 사용 가능한 이동방법이 다르므로 그것만 분류해주면 된다.

 

-direction 은 0은 가로, 1은 세로 , 2는 대각선이고

 case 1~7의 경우 문제에 표기된 그림의 순서 그대로 사용하였다.

#include<iostream>
#include<vector>
using namespace std;

int totalcount=0;
int housemap[17][17];
int N;
int x=1;
int y=2;
int dx[3] = { 0,1,1 }; //가로,세로,대각선이동
int dy[3] = { 1,0,1 };
int direction = 0; // 가로,세로,대각선 방향
void startsearch(int x,int y,int d) {
	if (x > N || y > N) return; //종료조건(미도착)
	if (x == N && y == N) { totalcount++; return; } //종료조건(도착
	if (d == 0) {
		if (housemap[x + dx[0]][y + dy[0]] != 1) 
		startsearch(x + dx[0], y + dy[0], 0); //case 1
		if (housemap[x + dx[2]][y + dy[2]] != 1 && housemap[x + dx[1]][y + dy[1]] != 1 && housemap[x + dx[0]][y + dy[0]] != 1) 
		startsearch(x + dx[2], y + dy[2], 2); //case 2
	}
	else if (d == 1) {
		if (housemap[x + dx[1]][y + dy[1]] != 1) 
		startsearch(x + dx[1], y + dy[1], 1); //case 3
		if (housemap[x + dx[2]][y + dy[2]] != 1 && housemap[x + dx[1]][y + dy[1]] != 1 && housemap[x + dx[0]][y + dy[0]] != 1)
		startsearch(x + dx[2], y + dy[2], 2); //case 4
	}
	else {
		if (housemap[x + dx[0]][y + dy[0]] != 1)
		startsearch(x + dx[0], y + dy[0], 0); //case 5
		if (housemap[x + dx[1]][y + dy[1]] != 1) 
		startsearch(x + dx[1], y + dy[1], 1); //case 6
		if (housemap[x + dx[2]][y + dy[2]] != 1 && housemap[x + dx[1]][y + dy[1]] != 1 && housemap[x + dx[0]][y + dy[0]] != 1) 
		startsearch(x + dx[2], y + dy[2], 2); //case 7
	}
}

int main() {
	cin >> N;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> housemap[i][j];
		}
	}
	if (housemap[N][N]!=1) { startsearch(x, y, direction); }
	cout << totalcount << "\n";
	return 0;
}

 

1. Redirection을 구현

 

Redirection(in) 구현 부

 

Main() 함수에서 자식 프로세스 exec을 수행하기 전에 “<”가 있는지 확인후

 

있을 경우 dup2함수를 이용하여 redirection 기능을 수행하도록 구현 하였습니다.

 

그리고 마지막 for문을 이용하여 이전 커맨드벡터에서 떙겨주었습니다

 

( 리다이렉션 명령어가 들어있던 부분)

 

 Redirection(out) 구현 부

 

마찬가지로 main()함수에서 자식프로세스가 exec을 하기 전에 redir_out함수로 들어가서

 

“>” 명령어가 있는지를 확인하고 있다면 dup2함수를 이용하여 redirection을 수행후

 

마지막 for문을 이용하여 커멘드벡터를 떙겨주었습니다.

 

( 리다이렉션 명령어가 들어있던 부분)

 

2. 파이프 처리 기능

 

받은 커맨드문장(cmdvector) 에서 파이프가 있는지 와 커맨드문장의 어느 위치에 파이프가

 

있는지를 확인합니다.

 

만약 파이프 명령어가 없다면 바로 리턴 합니다.(리턴 값 1)

 

그리고 for문을 통해서 파이프 명령어(“|”) 앞, 뒤 명령어들을 나눠줍니다.

 

그리고 파이프를 생성하여 줍니다.

 

그리고 첫 번째 받은 명령어를 리다이렉션을 이용하여 출력을 돌려줍니다.

 

그리고 함수 내에서 자식을 생성한 후 자식은 두번째 명령어를 실행하는데

 

dup함수와 리 다이렉션을 이용하여 입력을 첫 번째 명령어(cmdpipe1)로부터

 

입력을 받도록 리다이렉션을 합니다.그리고 결과의 출력이 표준출력이 아닌 파이프를

 

통해서 나가도록 파이프출력으로 내보내도록 dup함수를 통해 설정합니다.

 

그 후 exec을 실행합니다.

 

부모 프로세스는 3번째 명령어(cmdpipe3)를 수행합니다.

 

이 프로세는 입력을 파이프를 통해서 입력받도록 dup함수를 이용하여 설정해주고

 

그리고 출력을 redirection을 통하여 조절해줍니다.

 

- 파이프 란 ?

 # 간단하게 말하자면 한 프로세스의 출력이 다른 프로세스의 입력으로 들어가서

    두개의 프로세스가 inter-communication 을 하는 것이다.

 # FIFO basis

 # half duplex ( full duplex를 굳이 하자면 가능 하기는 하지만 이를 권고)

    (보내는 쪽은 보내기만, 받는 쪽은 받기만)

 # 공통 부모인 프로세스나 친척들 끼리 파이프를 사용가능 (parent-child뿐만 아니라 child-child도 가능(공통조상에서        파이프를 열였을 경우))

 # 공통조상이 아닌 프로세스들 끼리 파이프와 같은 기능을 사용하고 싶을 때는 FIFO 를 이용

 #  #include<iostream>

     int pipe(int filedes[2]);

 # 프로세스가 파이프를 통해 read를 하려고 하는 경우

     -1. pipe is not empty : read를 하고 즉시 리턴 한다. (리턴값은 읽은 데이터의 바이트 수)

     -2. pipe is empty : read가 block된다. ( write를 통해서 들어올 때까지 기다림)

 # 프로세스가 파이프를 통해 write를 하려고 하는 경우

     -1. pipe is not full : 즉시 write하고 리턴한다.

     -2. pipe is full : 빈(여유)공간이 만들어 질때 까지 block(기다림)

 # 파이프의 한쪽이 closed(닫힌경우)

     -1 . (write 가 닫혔을 때) read의 경우 데이터 파일을 다 읽고 나면 0을 리턴한다.

     -2 . (read 가 닫혔을 때) write의 경우 write를 해도 read할 프로세스가 없다.

          커널이 SIGPIPE라는 시그널을 보낸다.(write를 실행한 프로세스에게)

                (default 값은 죽는것.)

          시그널을 무시하거나 잡아서(catch) 핸들러를 수행하거나 할경우 -1을 리턴하고

          errno을 EPIPE로 셋팅한다.

 

+ Recent posts