mojo's Blog

Scheduling with Deadlines 본문

학교에서 들은거 정리/알고리즘설계와분석

Scheduling with Deadlines

_mojo_ 2021. 11. 25. 16:47

Problem

– Let J = {1, 2, …, n} be a set of jobs to be served.

– Each job takes one unit of time to finish.

– Each job has a deadline and a profit.

      • If the job starts before or at its deadline, the profit is obtained.

➢ Schedule the jobs so as to maximize the total profit (not all jobs have to be scheduled).

 

예를 들어서 다음과 같은 Job(Deadline, Profit)이 4개 존재한다고 하자

 

 

이때, 최대 이익을 낼 수 있는 경우는 job = [4, 1] 인 경우 total = 75 인 경우다.

또 다른 예를 살펴보도록 하자.

 

 

이 경우는 job = [1, 2, 4] 와 같이 잡을 수 있다.

즉 Greedy 접근법으로 

(1) profit 을 기준으로 내림차순으로 job들을 정렬하고 => O(nlogn)

(2) 정렬된 각 job에 대한 Scan을 함으로써 schedule 가능한 경우에 대해서 추가하는 방식이다. 

      linked-list로 구현할 경우 O(n^2), disjoint set으로 구현할 경우 O(nlogn) 

 

위 예시로 다시 구해보면 ...

0. S = EMPTY

1.S = {1} ?   =>   가능

2. S = {1, 2} ?   =>   가능

3. S = {1, 2, 3} ?   =>   불가능

4. S = {1, 2, 4} ?   =>   가능

 

 

 

Linked-List 로 구하는 방법은 다음과 같다.

 

 

 

Solution Code

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

struct Job {
	int job;
	int Deadline;
	int Profit;
};

struct Node {
	int job;
	int Deadline;
	int Profit;
	struct Node* next, * prev;
};

Job job[100];
Node* root, root_dummy, dummy[100];
int deadline[9] = { 1,6,3,3,5,4,1,2,4 };
int profit[9] = { 100,80,90,120,40,105,115,85,50 };
int max_deadline = 6, job_cnt, mem_pool;
bool visited[100];

void Print_all_node()
{
	Node* tmp;
	tmp = root;
	while (tmp->next) {
		tmp = tmp->next;
		printf("[%d, %d, %d] / ", tmp->job, tmp->Deadline, tmp->Profit);
	}
}

void set_node()
{
	root_dummy.next = root_dummy.prev = nullptr;
	root = &root_dummy;
}

Node* get_node(Job tmp)
{
	dummy[mem_pool].Deadline = tmp.Deadline;
	dummy[mem_pool].job = tmp.job;
	dummy[mem_pool].Profit = tmp.Profit;
	return &dummy[mem_pool++];
}

void Node_insert(Job tmp)
{
	int cnt = 1;
	Node* new_node;

	if (mem_pool == max_deadline)
		return;
	if (root->next == nullptr) {
		new_node = get_node(tmp);
		root->next = new_node;
		new_node->prev = root;
		visited[tmp.Deadline] = true;
	}
	else {
		Node* node_tmp = root;
		while (node_tmp->next) {
			node_tmp = node_tmp->next;
			if (node_tmp->Deadline > tmp.Deadline)
				break;
			cnt++;
		}
		if (cnt > tmp.Deadline)
			return;

		int x = tmp.Deadline;
		while (visited[x]) x--;
		if (x == 0)
			return;
		visited[x] = true;

		new_node = get_node(tmp);
		if (cnt == mem_pool) {
			node_tmp->next = new_node;
			new_node->prev = node_tmp;
		}
		else {
			node_tmp->prev->next = new_node;
			new_node->next = node_tmp;
			new_node->prev = node_tmp->prev;
			node_tmp->prev = new_node;
		}
	}
}

void PQ_insert(int n, int d, int p)
{
	int x;
	x = ++job_cnt;
	while ((x != 1) && (job[x / 2].Profit < p)) {
		job[x] = job[x / 2];
		x /= 2;
	}
	job[x].job = n, job[x].Deadline = d, job[x].Profit = p;
}

Job PQ_pop()
{
	int parent, child;
	Job item, temp;

	item = job[1], temp = job[job_cnt--];
	parent = 1, child = 2;
	while (child <= job_cnt) {
		if ((child < job_cnt) && (job[child].Profit < job[child + 1].Profit)) child++;
		if (temp.Profit >= job[child].Profit) break;
		job[parent] = job[child];
		parent = child;
		child *= 2;
	}

	job[parent] = temp;
	return item;
}

void Scheduling()
{
	int i, before;
	Job tmp;
	for (i = 0; i < 9; i++) {
		PQ_insert(i + 1, deadline[i], profit[i]);
	}

	set_node();

	for (i = 0; i < 9; i++) {
		printf("%d : ", i + 1);
		before = mem_pool;
		tmp = PQ_pop();
		Node_insert(tmp);
		Print_all_node();
		if (before == mem_pool)
			printf("X\n\n");
		else
			printf("O\n\n");
	}

}

int main() 
{
	Scheduling();

	return 0;
}

 

 

'학교에서 들은거 정리 > 알고리즘설계와분석' 카테고리의 다른 글

Scheduling with Deadlines with Disjoint Sets  (0) 2021.12.07
Disjoint Sets  (0) 2021.11.30
Scheduling  (0) 2021.11.23
Huffman Coding  (0) 2021.11.16
Subset Sum Problem  (0) 2021.11.09
Comments