시그널 핸들링: signal()로 자식이 종료되면 실행할 함수를 운영체제에 등록
signal()
int signo, void(*func)(int)alarm()
void timeout(int sig)
{
if(sig==SIGALRM)
puts("Time out!");
alarm(2);
}
void keycontrol(int sig)
{
if(sig==SIGINT)
puts("CTRL+C pressed");
}
int main(int argc, char *argv[])
{
int i;
signal(SIGALRM, timeout);
signal(SIGINT, keycontrol);
alarm(2);
for(i=0; i<3; i++)
{
puts("wait...");
sleep(100);
}
return 0;
}
sigaction()
struct sigaction
{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
}
sigaction() 호출하려면 sigaction이라는 구조체 선언 및 초기화해야 함
void timeout(int sig)
{
if(sig==SIGALRM)
puts("Time out!");
alarm(2);
}
int main(int argc, char *argv[])
{
int i;
struct sigaction act;
act.sa_handler=timeout;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGALRM, &act, 0);
alarm(2);
for(i=0; i<3; i++)
{
puts("wait...");
sleep(100);
}
return 0;
}
void read_childproc(int sig)
{
int status;
pid_t id=waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status))
{
printf("Removed proc id: %d \n", id);
printf("Child send: %d \n", WEXITSTATUS(status));
}
}
int main(int argc, char *argv[])
{
pid_t pid;
struct sigaction act;
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &act, 0);
pid=fork();
if(pid==0) /* 자식 프로세스 실행 영역 */
{
puts("Hi! I'm child process");
sleep(10);
return 12;
}
else /* 부모 프로세스 실행 영역 */
{
printf("Child proc id: %d \n", pid);
pid=fork();
if(pid==0) /* 또 다른 자식 프로세스 실행 영역 */
{
puts("Hi! I'm child process");
sleep(10);
exit(24);
}
else
{
int i;
printf("Child proc id: %d \n", pid);
for(i=0; i<5; i++)
{
puts("wait...");
sleep(5);
}
}
}
return 0;
}

string solution(int m, int n, vector<string> board) {
string answer = "";
// 시작
// 전체를 훑는다
// 흰 칸은 전부 visited 처리
// 바로 짝이 연결되는 문자들은 우선순위 큐에 넣고 visited 처리
// 흰 칸에 노출된 문자는 알파벳 배열에 기록한 뒤 visited 처리
// 제거 시도
// 알파벳 배열을 훑으며 두번째 배열이 차 있으면 제거 시도한다
// (하우, 우하 두 방향 시도)
// 제거가 가능하다면 우선순위 큐에 넣는다
// 우선순위 큐에서 하나를 꺼내고 제거 가능한지 확인한다.
// 제거 가능 여부 확인 중 벽을 만났다면 바로 IMPOSSIBLE
// 추가 탐색
// 우선순위 큐에서 하나 뺀 후에 제거한다
// 제거 시 해당 문자의 알파벳 배열 값은 초기화한다
// 제거된 문자 두개와 붙어있고 visited하지 않은 타일들을 알파벳 배열에 기록한다
// 알파벳 배열을 다시 훑으며 연결이 가능한 값이 있는지 확인한다
// 종료
// 우선순위 큐가 비었으면 while문을 종료한다
// 알파벳 배열을 확인하고, 아직 값이 남아있다면 IMPOSSIBLE
vvp alpbt = vvp(26, vp(2, {-1,-1}));
vvb visited = vvb(m,vb(n));
vi diri = {0,0,1,-1};
vi dirj = {1,-1,0,0};
priority_queue<int, vector<int>, greater<int>> pq;
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
if(visited[i][j]) continue;
char b = board[i][j];
if(b=='.' || b=='*')
{
visited[i][j] = true;
}
else
{
for(int k=0; k<4; k++)
{
int newi = i+diri[k];
int newj = j+dirj[k];
if(newi<0||m<=newi||newj<0||n<=newj) continue;
int idx = b-'A';
if(board[newi][newj] == b)
{
alpbt[idx][0] = {i,j};
alpbt[idx][1] = {newi, newj};
visited[i][j]==true;
visited[newi][newj]=true;
pq.push(idx);
break;
}
else if (board[newi][newj] == '.')
{
if(alpbt[idx][0].first == -1)
{
}
}
}
}
}
}
return answer;
}
코드가 말도 안되게 길어지길래 정답을 봤더니
내 코드는 과최적화를 하고 있었다.
타일들 기록해두고 계속 순회하면서 제거 가능한지만 보면 됐다.
그럼 시간 복잡도는 O((알파벳개수^2*(m+n)) 라서, 충분히 가능
배열도 알파벳을 인덱스로 그대로 사용하고, 순서대로 훑으니까 우선순위 큐로 억지 정렬 해줄 필요도 없다
using namespace std;
typedef pair<int, int> pii;
typedef vector<pii> vp;
typedef vector<vp> vvp;
bool HorizontalEmpty(int li, int hi, int j, vector<string>& board, char tileC)
{
for(int i=li; i<=hi; i++)
{
char b = board[i][j];
if(b!='.'&&b!=tileC) return false;
}
return true;
}
bool VerticalEmpty(int i, int lj, int hj, vector<string>& board, char tileC)
{
for(int j=lj; j<=hj; j++)
{
char b = board[i][j];
if(b!='.'&&b!=tileC) return false;
}
return true;
}
bool CanPop(pii t1, pii t2, vector<string>& board)
{
int t1i, t1j, t2i, t2j;
tie(t1i, t1j) = t1;
tie(t2i, t2j) = t2;
char tileC = board[t1i][t1j];
bool f1 = t1i <= t2i;
bool f2 = t1j <= t2j;
int li, hi, lj, hj;
li = f1 ? t1i : t2i;
hi = f1 ? t2i : t1i;
lj = f2 ? t1j : t2j;
hj = f2 ? t2j : t1j;
bool leftEmpty = VerticalEmpty(li,lj,hj,board,tileC);
bool rightEmpty = VerticalEmpty(hi,lj,hj,board,tileC);
bool downEmpty = HorizontalEmpty(li,hi,lj,board,tileC);
bool topEmpty = HorizontalEmpty(li,hi,hj,board,tileC);
if((f1&&f2) || (!f1&&!f2)) // 좌상 대각선
{
// 좌+상이 비었거나, 우+하가 비었거나
if(leftEmpty&&topEmpty) return true;
if(rightEmpty&&downEmpty) return true;
}
else // 우하 대각선
{
// 좌+하가 비었거나, 우+상이 비었거나
if(leftEmpty&&downEmpty) return true;
if(rightEmpty&&topEmpty) return true;
}
return false;
}
// 전역 변수를 정의할 경우 함수 내에 초기화 코드를 꼭 작성해주세요.
string solution(int m, int n, vector<string> board) {
string answer = "";
vvp tiles = vvp(26,vp());
int idx = 0;
// 타일을 전부 순회하면서 vvp에 정보를 기록해둔다
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
char b=board[i][j];
if(b!='.'&&b!='*')
{
tiles[b-'A'].push_back({i,j});
idx++;
}
}
}
// 알파벳을 계속 훑으면서, 터진게 있는지 확인
// 터졌다면 vvp를 초기화시키고 터진 char 반환
// 아무것도 안 터졌으면 종료
// 종료됐을 때 cnt!=0이면 IMPOSSIBLE 출력, cnt면 이제까지 모았던 char 출력
bool explosion = true;
while(explosion)
{
explosion = false;
for(int i=0; i<size(tiles); i++)
{
if(size(tiles[i])==0) continue;
int t1i, t1j, t2i, t2j;
tie(t1i, t1j) = tiles[i][0];
tie(t2i, t2j) = tiles[i][1];
if(CanPop(tiles[i][0],tiles[i][1],board))
{
explosion = true;
answer+=board[t1i][t1j];
board[t1i][t1j] = '.';
board[t2i][t2j] = '.';
tiles[i]=vp();
idx-=2;
break;
}
}
}
cout << answer;
if(idx==0) return answer;
else return "IMPOSSIBLE";
}
실수