[알고리즘] 문제풀이 연습

[알골90제] 46번 - 멀티태스킹 (카카오 먹방 문제 변형)

ddgoori 2019. 7. 26. 16:52

입력

 

1) N개

2) N개만큼 각 처리해야할 시간 입력

3) 정전 발생한 시간

 

* 컴퓨터는 1번 작업부터 순서대로 1초씩 작업을 합니다. 각 1초만 작업하고 다음 작업으로 넘어가야합니다.

* 마지막 번호의 작업을 1초했으면 다시 첫번째 작업을 해야합니다. 

* 처리가 다 끝난 작업은 사라지고 새로운 작업은 들어오지 않습니다.

 

여기서 구해해야할 것 출력!

정전 후 몇번 작업부터 다시 시작해야하냐는 것입니다. 

*이때 주의할 것은 정전이 되기 직전 끝낸 작업에서 그 다음 작업을 구하는 것입니다.

 

입력예제를 들어보겠습니다.

3 //몇개의 작업
1 //작업별 처리 시간 - 작업번호 1
2 //작업별 처리 시간 - 작업번호 2
3 //작업별 처리 시간 - 작업번호 3: 마지막 작업 번호
5 //정전 시간

출력 : 3

 

코드는 아래와 같습니다.

 

//46번 - 멀티태스킹(카카오 먹방 문제 변형)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;

int main() {

	int n, k, pos = 0, sec = 0, total=0;
	scanf("%d", &n); 	//작업할 갯수를 받고
	vector<int> a(n+1); 	//벡터로 처리시간을 저장할 공간을 만들어줍니다.
	
	for (int i = 1; i <= n; i++) {	//처리시간을 벡터 공간에 저장해줍니다.
		scanf("%d", &a[i]);
		total += a[i];
	//total이 필요한 이유는 작업시간이 다 끝나있다면 정전이 되어도 처리해야할 작업이 없기때문에
    //-1로 출력해줘야 하는데요. 이때 총 정전시간 k가 작업시간보다 크거나 같으면 이미
    //작업이 다 끝났다는 것이기 때문에 -1을 출력해주기 위해 total에 모든 작업시간을 누적해서 쌓습니다.
    }

	scanf("%d", &k);	//정전 시간을 받습니다.

	//정전된 시간이 총작업을 합친시간보다 많다면 이미 스케줄이 다 끝나있는 상태겠죠?
    //그렇기 때문에 더 이상 처리할 작업이 없다는 뜻의 -1을 출력해줍니다.
    //출력 후 return 0으로 프로그램도 종료해주고요.
	if (k >= total) {
		printf("-1\n");
		return 0;
	}

	//pos의 역할: 포인터와 같은 역할을 하는데요. 배열의 자리를 가리킵니다.
    //특히 pos가 n보다 커진다면 다시 첫번째 배열부터 순환해야하기 때문에 pos = 1로 만들어줄때 쓰입니다.
	while (1) {
		//A
		pos++;

		if (pos > n)
			pos = 1; 	//n이 3이고 pos가 4이면? 배열의 끝자리의 자리를 지났다는 것이기에
            			//다시 처음으로  돌아갈 수 있도록 pos=1을 해줍니다.

		if (a[pos] == 0) continue;
		//continue시 아래 작업은 안하고 반복문으로 갑니다. A지점
        //0이 들어가있다는 것은 작업이 다 끝난 다는 말입니다.
        //작업이 다 끝났으면 그 다음 공간으로 가야하기때문에 아래의 처리누적시간을 계산한다거나
        //해당배열 자리의 값을 --해줘서 작업을 해준다거나 하는 것은 하지 않습니다.
        //바로 다음 배열로 가기위해서 continue하여 while문의 가장 첫번째 코드인 pos++를 해주는 것이죠.
	
    	//만약에 현재 pos가 가리키는 자리에 0이 아닌 숫자가 담겨있다면 작업을 해줘서 줄여야합니다.
        //작업은 1초씩 되기때문에 --하고, 작업한 시간의 합산인 sec변수를 ++해줍니다.
        //sec를 알아야 정전시간k가 되었을때 작업이 멈추거든요.
		a[pos]--;
		sec++;
		if (sec == k) break; //총작업시간이 흘러서 정전시간 k와 같아지면 반복문을 나갑니다.
	}
	
    //다시 while문으로 반복문을 들어가는데요.
    //pos는 작업이 끝나고 -> 정전이 일어난 상태에서 멈춰있기 때문에
    //그 다음 작업이 어디서 시작되는지 알기 위해서는 pos++해줍니다.
	while (1) {
		pos++; //다음 작업위치 n=3이면 1,2,3 중에 하나겠죠 
		if (pos > n) pos = 1; //만약에 pos가 n을 넘어버리면 예를들어 그 전에 3까지 작업했으니
        					  //그 다음에 1 작업해야 하잖아요. 그러니 n을 넘으면 pos = 1을 해줍니다.
		if (a[pos] != 0) break; //그리고 a[pos]가 0이 아니면 끝냅니다. 
        						//0은 이미 작업이 끝났으니 지나쳐야하는것이고, pos++할때마다 0이 있으면
                                //다음 작업을 찾아야하기 때문에 while문으로 돌면서
                                //0이 아닌 다음 작업을 찾을때까지 도는 것입니다.
	}
	//그리고 정전 후 처리해야할 0이 아닌 어떤 값이 들어 있는 자리 작업번호 즉, 배열의 번호를 출력
    //문제에 나와있는대로 이해하면 작업번호는 값에 상관없이 입력되는 순서대로 1,2,3,4,5...로 들어가있거든요.
	//입력순으로 부여된 작업번호를 출력하는 것이지 처음 입력한 값을?출력하는게 아님! 작업 번호임
    printf("%d", pos);
}

 

어려웠던 점:

  • 배열이 끝나면 다시 순환하는 것에 대한 조건문
  • 1초씩 처리한 것을  어떻게 표현? => 그 자리 --하면 됨
  • 다 처리된 것은 조건문 어떻게 표현? => if(a[pos] ==0 ) continue; 아래 작업 진행하지 않고 pos++해서 다시 0이아닌 것들 찾기
  • a[pos]가 0이 아니라면 컨티뉴문은 지나가게 되고 어떤 숫자가 들어있는 곳은 작업이 처리되기 때문에 1씩 -가 된다는 것
  • 작업한 시간이 정전시간과 같으면 반복문을 나가야한 다는 점 => 이 부분이 정전 후 다음 작업이 어딘가?를 알아내기 위한 부분. 정전시간과 작업했던게 같다는 말은...해당작업을 진행한만큼 시간이 흘렀다는 것...
  • 정전이 되엇을 때 어디까지 작업했는지 구했으니, 이제 그 다음에 작업할 부분이 어딘지 구해야함
  • 일단 0은 작업이 다 끝났으니.... 0이 아닌 부분을 만나면 break해야함. 왜냐하면 0이 아니라는게 정전 전 작업이 끝나고 처음만나는 작업해야할 곳의 작업 번호 이기 때문! => 이때 주의해야할 것은 pos를 계속 ++해서 0이아닌 작업을 찾아가는 과정에서 pos가 n을 넘겨버리면 다시 pos=1로 설정해서 순환시켜줘야한 다는 점이다. a[pos]가 0이 아닌 작업물을 찾게 되면 나오고 해당 작업 번호를 찍어주면 됨!

 

 

*이 게시물은 개인 공부용으로 작성한 것입니다.