4번 문제   

 



    내가 풀이한 답   

 

 앞에서 풀었던 경로 탐색에서 조금 변형된 문제라고 생각했다. 기존에는 간선에 1 값을 넣었는데 1 값 대신에 가중치 값을 넣었고 temp 변수를 하나 선언하고 종점에 도달하기 전까지 더해서 종점에 도착하면 최솟값과 비교하는 것을 생각했다. 주의할 점은 아래 그림에서 두 번째 경로를 찾을 때 2-3, 3-4번으로 가는 가중치 값을 빼주는 것처럼 check값이 0으로 변할 때 temp에 가중치값도 빼줘야 한다. 

 

//#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int map[21][21], check[21], n, minValue=77777, temp=0;

int dfs(int v){
	if(v==n){
		if(minValue > temp) minValue = temp;
	}
	else {
		for(int i=1; i<=n; i++){
			if(map[v][i]!=0 && check[i] == 0){
				check[i] = 1;
				temp += map[v][i];
				dfs(i);
				check[i] = 0;
				temp -= map[v][i];
			}
		}
	}
}

int main() {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);
	
	int m, i, a, b, c;
	cin >> n >> m;
	
	for(i=0; i<m; i++){
		cin >> a >> b >> c;
		map[a][b] = c;
	}

	check[1] = 1;
	dfs(1);

	cout << minValue;
	return 0;
}

 

 

 결과는 통과하였다.

 

 


 

    사이트의 답안   

 

#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
int map[30][30], ch[30], n, cost=2147000000;	

void DFS(int v, int sum){
	int i;
	if(v==n){
		if(sum<cost) cost=sum;
	}
	else{
		for(i=1; i<=n; i++){
			if(map[v][i]>0 && ch[i]==0){
				ch[i]=1;
				DFS(i, sum+map[v][i]);
				ch[i]=0;
			}
		}
	}
}
int main(){
	freopen("input.txt", "rt", stdin);
	int m, i, a, b, c;
	scanf("%d %d", &n, &m);
	for(i=1; i<=m; i++){
		scanf("%d %d %d", &a, &b, &c);
		map[a][b]=c;
	}
	ch[1]=1;
	DFS(1, 0);
	printf("%d\n", cost);
	
	return 0;
}

 

 사이트의 답은 sum 값을 dfs 파라미터 인자로 넘겨주고 stack의 특성을 이용해서 sum 값이 stack에 저장되도록 하였다. 

    3번 문제   

 

 



    내가 풀이한 답   

 

 논리적인 흐름은 바뀌지 않고 자료 구조만 바뀌었다. 기존에 이차원 배열이었던 것을 21개의 벡터로 선언하였고 방문 체크를 위한 일차원 배열도 21 크기의 벡터 하나를 선언하였다. 

//#include <bits/stdc++.h>
#include <iostream>
#include <vector>
using namespace std;

vector<int> map[21], check(21);
int n, cnt=0;

void dfs(int v){
	if(v==n) cnt++;
	else {
		for(int i=0; i<map[v].size(); i++){
			if(check[map[v][i]]==0){
				check[map[v][i]] = 1;
				dfs(map[v][i]);
				check[map[v][i]] = 0;
			}
		}
	}
}
 
int main() {
	freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);
	
	int m, i, a, b;
	cin >> n >> m;
	
	for(i=0; i<m; i++){
		cin >> a >> b;
		map[a].push_back(b);
	}
	
	check[1] = 1;
	dfs(1);
	
	cout << cnt;

	return 0;
}

 

 

 결과는 통과하였다.

 

 


 

    사이트의 답안   

 

#include<stdio.h>
#include<vector>
using namespace std;
int ch[30], cnt=0, n;		
vector<int> map[30];
void DFS(int v){
	int i;
	if(v==n){
		cnt++;
	}
	else{
		for(i=0; i<map[v].size(); i++){
			if(ch[map[v][i]]==0){
				ch[map[v][i]]=1;
				DFS(map[v][i]);
				ch[map[v][i]]=0;
			}
		}
	}
}			
int main(){
	freopen("input.txt", "rt", stdin);
	int m, i, a, b;
	scanf("%d %d", &n, &m);
	for(i=1; i<=m; i++){
		scanf("%d %d", &a, &b);
		map[a].push_back(b);
	}
	ch[1]=1;
	DFS(1);
	printf("%d\n", cnt);
	return 0;
}

 

 

    2번 문제   

 



    내가 풀이한 답   

 

 문제에서는 7 X 7 형태로 정해져 있었지만 이해를 위해 3 X 3을 기준으로 생각을 해보았다. 한 좌표에서 위, 아래, 오른쪽, 왼쪽을 접근하려면 더 큰 인덱스가 필요했다. 그 결과 (N+2) X (N+2) 형태면 가능하다고 보았다. 아래 그림에서 도착점까지 갈 수 있는 방법은 총 두 가지고 그 중 한 가지의 시퀀스는 다음과 같다. →, ↓, ←, ↑ 순서로 탐색한다고 가정했다.

 

 

//#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int map[9][9], check[9][9], cnt = 0;
int x[4] = {1, 0, -1, 0};
int y[4] = {0, 1, 0, -1};

void dfs(int a, int b){
	int xx, yy, i;
	if(a==7 && b==7) cnt++;
	else {
		for(i=0; i<4; i++){
			xx = x[i] + a;
			yy = y[i] + b;
			
			if(xx < 1 || yy < 1 || xx > 7 || yy > 7) continue;
			if(map[xx][yy] == 0 && check[xx][yy] == 0){
				check[xx][yy] = 1;
				dfs(xx, yy);
				check[xx][yy] = 0;
			}
		}
	}
}

int main() {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);
	
	int i, j;
	
	for(i=1; i<=7; i++){
		for(j=1; j<=7; j++){
			cin >> map[i][j];		
		}
	}	
	
	check[1][1] = 1;
	dfs(1, 1);
	
	cout << cnt;
	
	return 0;
}

 

 

 결과는 통과하였다.

 

 


 

    사이트의 답안   

 

#include<stdio.h>
int map[10][10], ch[10][10];
int dx[4]={1, 0, -1, 0};
int dy[4]={0, 1, 0, -1};
int cnt=0;

void DFS(int x, int y){	
	int xx, yy, i;
	if(x==7 && y==7){
		cnt++;
	}
	else{
		for(i=0; i<4; i++){
			xx=x+dx[i];
			yy=y+dy[i];
			if(xx<1 || xx>7 || yy<1 || yy>7)
				continue;
			if(map[xx][yy]==0 && ch[xx][yy]==0){
				ch[xx][yy]=1;
				DFS(xx, yy);
				ch[xx][yy]=0;
			}		
		}
	}
}

int main(){
	freopen("input.txt", "r", stdin);
	int i, j;
	for(i=1; i<=7; i++){
		for(j=1; j<=7; j++){
			scanf("%d", &map[i][j]);
		}
	}
	ch[1][1]=1;
	DFS(1, 1);
	printf("%d\n", cnt);
	return 0;
}

 

 

 

    1번 문제   

 

 



    내가 풀이한 답   

 

 문제에 있는 예제는 다음과 같은 과정을 거친다. check 배열을 통해 이미 접근한 노드에 다시 접근하는 것을 방지하고 dfs 재귀 함수를 호출하였다.

 

 

 

//#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int map[21][21], check[21], n, cnt=0;

void dfs(int v){
	if(v==n) cnt++;
	else {
		for(int i=1; i<=n; i++){
			if(map[v][i] == 1 && check[i] == 0){
				check[i] = 1;
				dfs(i);
				check[i] = 0;
			}
		}
	}
}

int main() {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);
	
	int m, i, a, b;
	cin >> n >> m;
	
	for(i=0; i<m; i++){
		cin >> a >> b;
		map[a][b] = 1;
	}
	
	check[1] = 1;
	dfs(1);
	
	cout << cnt;
	return 0;
}

 

 

 결과는 통과하였다.

 

 


 

    사이트의 답안   

 

<경로도 함께 출력하는 코드>
#include<stdio.h>	
int map[30][30], ch[30], cnt=0, n, path[30];
void DFS(int v, int L){
	int i, j;
	if(v==n){
		cnt++;
		for(j=0; j<L; j++){
			printf("%d ", path[j]);
		}
		puts("");
	}
	else{
		for(i=1; i<=n; i++){
			if(map[v][i]==1 && ch[i]==0){
				ch[i]=1;
				path[L]=i;
				DFS(i, L+1);
				ch[i]=0;
			}
		}
	}
}
				
int main(){
	freopen("input.txt", "rt", stdin);
	int m, i, j, a, b, c;
	scanf("%d %d", &n, &m);
	for(i=1; i<=m; i++){
		scanf("%d %d", &a, &b);
		map[a][b]=1;
	}
	ch[1]=1;
	path[0]=1;
	DFS(1, 1);
	printf("%d\n", cnt);
	return 0;
}

 

 

    4번 문제   

 



    내가 풀이한 답   

 

 장애물이 없는 경우와 장애물이 있는 경우를 살펴보면 장애물이 없을 때 (1, 1)에서 (3, 3)까지 갈 수 있는 방법은 6가지이고 장애물이 있을 때에는 2가지이다. 

 

 한 칸 아래 또는 한 칸 오른쪽으로 갈 수 있으므로 점화식은 f(m, n) = f(m-1, n) + f(m, n-1)이다. 장애물 같은 경우는 갈 수 있는 경우의 수가 0이므로 0으로 설정해준다. 

 

 

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

int a[101][101];
int solution(int m, int n, vector<vector<int>> puddles) {
    for(int i=0; i<puddles.size(); i++){
        a[puddles[i][0]][puddles[i][1]] = -1;
    }
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            if(i==1 && j==1) a[i][j] = 1;
            else if(a[i][j] == -1) a[i][j] = 0;
            else a[i][j] = (a[i-1][j] + a[i][j-1])%1000000007;
        }
    }
    return a[m][n];
}


 

 

 결과는 통과하였다.

 

'알고리즘 & 자료구조 > 동적 계획법' 카테고리의 다른 글

6. 가방 문제 (Knapsack)  (0) 2020.10.23
5. 가방 문제 (Knapsack)  (0) 2020.10.23
3. 정수 삼각형  (0) 2020.09.21
2. 알리바바와 40인의 도둑  (0) 2020.09.21
1. 네트워크 선 자르기  (1) 2020.09.21

    3번 문제   

 



    내가 풀이한 답   

 

 Bottom-up 방식으로 접근하였고 2번 알리바바와 40인의 도둑과 매우 비슷한 유형의 문제라고 생각했다. 정수 삼각형 역시 경우의 수를 생각해 보았다. 

 

 첫 번째는 보라색 부분과 같이 오른쪽 대각선으로만 올 수 있는 경우였다. 이는 대각선 방향의 왼쪽값과 해당 위치의 값을 더해주었다.

 

 두 번째는 하늘색 부분가 같이 왼쪽 대각선으로만 올 수 있는 경우였다. 이는 위쪽 값과 해당 위치의 값을 더해주었다.

 

 마지막으로는 오른쪽과 왼쪽 대각선으로 둘 다 올 수 있는 경우였다. 이는 대각선 방향의 왼쪽값과 위쪽 값 중 제일 작은 값과 해당 위치의 값을 더해주었다.  

 

 

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

int arr[500][500];
int solution(vector<vector<int>> triangle) {
    int i, j, ans=0;
    for(i=0; i<triangle.size(); i++){
        for(j=0; j<triangle[i].size(); j++){
            if(i==0 && j==0) arr[i][j] = triangle[i][j];
            else if(j==triangle[i].size()-1) arr[i][j] = arr[i-1][j-1] + triangle[i][j];
            else if(j==0 && i!=0) arr[i][j] = arr[i-1][j] + triangle[i][j];
            else arr[i][j] = max(arr[i-1][j-1], arr[i-1][j]) + triangle[i][j];
        }
    }
    for(i=0; i<triangle[triangle.size()-1].size()-1; i++){
        ans = max(ans, arr[triangle.size()-1][i]);
    }
    return ans;
}

 

 

 결과는 통과하였다.

 



    다른 사람들의 풀이   

 

#include <string>
#include <vector>

using namespace std;

int solution(vector<vector<int>> triangle) {

    //바닥부터 큰 값의 수를 윗 칸에 더해나간다
    for(int i = triangle.size()-2; i > -1; i--){
        for(int j = 0; j <= i; j++){
            triangle[i+1][j] > triangle[i+1][j+1] ? triangle[i][j] += triangle[i+1][j] : triangle[i][j] += triangle[i+1][j+1];
        }
    }

    return triangle[0][0];
}

 

 제일 끝 부분부터 큰 값의 수를 더해간다는 것이 인상 깊었다. 전혀 생각지도 못한 풀이였다.

 

 

'알고리즘 & 자료구조 > 동적 계획법' 카테고리의 다른 글

6. 가방 문제 (Knapsack)  (0) 2020.10.23
5. 가방 문제 (Knapsack)  (0) 2020.10.23
4. 등굣길  (0) 2020.09.22
2. 알리바바와 40인의 도둑  (0) 2020.09.21
1. 네트워크 선 자르기  (1) 2020.09.21

    2번 문제   

 

 



    내가 풀이한 답   

 

 Bottom-up 방식으로 접근하였고 이차원 배열에서 접근할 수 있는 경우의 수를 생각해 보았다. 현재 기준에서 오른쪽과 아래쪽으로만 갈 수 있기 때문에 총 3가지의 경우의 수가 존재했다. 

 

 첫 번째는 보라색 부분과 같이 오른쪽에서만 올 수 있는 경우였다. 이는 왼쪽 값과 입력된 값을 더해주었다.

 두 번째는 하늘색 부분가 같이 아래쪽에서만 올 수 있는 경우였다. 이는 위쪽 값과 입력된 값을 더해주었다.

 마지막으로는 오른쪽과 아래쪽 둘 다 올 수 있는 경우였다. 이는 오른쪽과 아래쪽 중 제일 작은 값을 찾아 입력된 값을 더해주었다. 

 

 

#include <algorithm>
using namespace std;

int arr[21][21];
int main() {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);

	int n, i, j, a;
	cin >> n;
	
	for(i=1; i<=n; i++){ 
		for(j=1; j<=n; j++){
			cin >> a;
			if(i==1 && j==1) arr[i][j] = a;
			else if(i==1 && j!=1) arr[i][j] = arr[i][j-1] + a;
			else if(j==1 && i!=1) arr[i][j] = arr[i-1][j] + a;
			else arr[i][j] = min(arr[i-1][j], arr[i][j-1]) + a;		
		}
	}	
	
	cout << arr[n][n];
	return 0;
}

 

 

 결과는 통과하였다.

 

 



    사이트의 답안   

 

#include<bits/stdc++.h>
using namespace std;
int arr[21][21], dy[21][21];
int main(){
	ios_base::sync_with_stdio(false);
	freopen("input.txt", "rt", stdin);
	int n, cnt=0;
	cin>>n;
    
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			cin>>arr[i][j];
		}
	}
    
	dy[0][0]=arr[0][0];
	for(int i=1; i<n; i++){
		dy[0][i]=dy[0][i-1]+arr[0][i];
		dy[i][0]=dy[i-1][0]+arr[i][0];
	}
    
	for(int i=1; i<n; i++){
		for(int j=1; j<n; j++){
			dy[i][j]=min(dy[i-1][j], dy[i][j-1])+arr[i][j];
		}
	}
	cout<<dy[n-1][n-1];
	return 0;
}

 

  사이트의 답도 3가지 경우의 수로 나눠서 접근했다. 위쪽에서 오는 경우와 왼쪽에서 오는 경우를 한 번에 처리하는 부분이 좀 인상 깊었다. 나는 왜 저 생각을 못했을까

 


 

    또 다른 방법 - Top Down 방식   

 

//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;

int arr[21][21], dp[21][21];

int dfs(int a, int b){
	if(dp[a][b]>0) return dp[a][b];
	if(a==1 && b==1) return arr[1][1];
	else {
		if(a==1 && b!=1) return dp[a][b] = dfs(a, b-1) + arr[a][b];
		else if(b==1 && a!=1) return dp[a][b] = dfs(a-1, b) + arr[a][b];
		else  return dp[a][b] = min(dfs(a-1, b), dfs(a, b-1)) + arr[a][b];
	}
}

int main() {
	//freopen("input.txt", "rt", stdin);
	ios_base::sync_with_stdio(false);

	int n, i, j;
	cin >> n;
	
	for(i=1; i<=n; i++){
		for(j=1; j<=n; j++){
			cin >> arr[i][j];
		}
	}
	
	cout << dfs(n, n);
	return 0;
}

 

  사이트의 답과 논리적으로 똑같았다. 

 

'알고리즘 & 자료구조 > 동적 계획법' 카테고리의 다른 글

6. 가방 문제 (Knapsack)  (0) 2020.10.23
5. 가방 문제 (Knapsack)  (0) 2020.10.23
4. 등굣길  (0) 2020.09.22
3. 정수 삼각형  (0) 2020.09.21
1. 네트워크 선 자르기  (1) 2020.09.21

    1번 문제   

 



    내가 풀이한 답   

 

 Bottom-up 방식으로 직관적으로 구할 수 있는 작은 해들을 구하고 그 작은 해를 이용해서 큰 해를 차례로 구해서 점화식을 도출하였다. 

 

 

#include <iostream>
using namespace std;

int a[50];
int main() {
	//freopen("input.txt", "rt", stdin);

	ios_base::sync_with_stdio(false);
	int n, i; 
	cin >> n;
	
	a[1] = 1;
	a[2] = 2;
	
	for(i=3; i<=n; i++){
		a[i] = a[i-2] + a[i-1];
	}
	
	cout << a[n];
	
	return 0;
}

 

 

 결과는 통과하였다.

 

 



    사이트의 답안   

 

#include<bits/stdc++.h>
using namespace std;
int dy[50];
int main(){
	ios_base::sync_with_stdio(false);
	freopen("input.txt", "rt", stdin);
    
	int n;
	cin>>n;
	dy[1]=1;
	dy[2]=2;
    
	for(int i=3; i<=n; i++){
		dy[i]=dy[i-1]+dy[i-2];
	}
    
	cout<<dy[n];
	return 0;
}

 

  사이트의 답과 논리적으로 똑같았다. 

 


 

    또 다른 방법 - Top Down 방식   

 

 Top-Down 방식으로도 풀 수 있는데 이 방식은 재귀 + 메모이제이션을 이용한 방식이다. 아래 그림과 같이 재귀식으로 함수를 호출하고 입력 값이 큰 수일수록 반복되는 재귀 함수가 많으므로 시간이 오래걸리기 때문에 메모이제이션 방식으로 한 번 호출한 적이 있으면 그 값을 바로 리턴해서 시간복잡도를 줄일 수 있다. 

 

 

#include<bits/stdc++.h>
using namespace std;
int dy[50];
int main(){
	ios_base::sync_with_stdio(false);
	freopen("input.txt", "rt", stdin);
    
	int n;
	cin>>n;
	dy[1]=1;
	dy[2]=2;
    
	for(int i=3; i<=n; i++){
		dy[i]=dy[i-1]+dy[i-2];
	}
    
	cout<<dy[n];
	return 0;
}

 

  사이트의 답과 논리적으로 똑같았다. 

 

 

'알고리즘 & 자료구조 > 동적 계획법' 카테고리의 다른 글

6. 가방 문제 (Knapsack)  (0) 2020.10.23
5. 가방 문제 (Knapsack)  (0) 2020.10.23
4. 등굣길  (0) 2020.09.22
3. 정수 삼각형  (0) 2020.09.21
2. 알리바바와 40인의 도둑  (0) 2020.09.21

   프로토콜이란 무엇인가?   

 

 

 일상 생활에서 지켜야 하는 약속이 있듯이, 네트워크에서 문제 없이 통신하려면 약속(규칙)을 지켜야 한다. 예를 들어, 언어가 서로 다른 외국인들이 대화를 하려고 하면 서로 알아들을 수 없기 때문에 곤란함을 겪을 것이다. 하지만, 서로 알아들을 수 있는 언어를 정해놓고 대화를 한다면 문제가 없을 것이다. 

 

 

 

 이처럼 네트워크에서도 컴퓨터 간에 정보를 주고 받을 때 통신 방법에 대한 규칙을 정해 놓는데 이를 프로토콜(protocol)이라고 한다. 편지를 예로 들면, 편지를 쓰고 편지를 우체통에 넣을 때 주소를 적지 않거나 우표를 붙이지 않은 채로 넣게되면 편지를 어디로 보내야 할 지 알 수 없으므로 우편 배달부는 곤란해진다. 

 

 따라서, 이런 곤란한 상황이 발생하지 않도록 몇 가지 규칙을 정해야 한다. 규칙에는 편지를 쓰는 규칙, 편지를 보내는 규칙, 우체국의 규칙 등 여러 규칙이 있는데 서로 독립적인 여러 규칙을 거쳐야 한다. 

 


 

   통신 규격 - OSI 모델  

 

 지금은 상상도 할 수 없지만 예전에는 같은 회사의 컴퓨터끼리만 통신이 가능했다고 한다. 즉, A 사의 컴퓨터와 B 사의 컴퓨터와는 통신할 수 없었다. 이런 곤란한 상황이 발생하지 않도록 공통으로 사용할 수 있는 표준 규격을 정해야 했다. 네트워크에서는 국제 표전화기구(ISO)의 OSI 모델TCP/IP 모델과 같이 데이터를 주고받기 위한 통신 규격이 정해져 있다. 

 

 컴퓨터에서 컴퓨터로 데이터를 송, 수신 할 때 컴퓨터 내부에서는 여러 가지 일을 한다. 이 때, OSI 모델을 적용한다면 일곱 개의 계층(레이어)에서 일을 하게 된다. 

 

 

 


 

   통신규격 - TCP/IP 모델   

 

 TCP/IP 모델은 인터넷 모델이라고도 하며, 아래 그림과 같이 OSI 모델에서 응용, 표현, 세션 계층이 TCP/IP 모델에서 응용으로 합쳐지고 물리, 데이터 링크 계층이 네트워크 접속 계층으로 합쳐져 일곱 개의 계층에서 네 개의 계층으로 줄었다. 그리고 각각 계층에는 다양한 프로토콜들이 존재한다. 

 

 

 


 

   데이터 전송   

 

 OSI 모델 통신 규격으로 데이터 전송하는 과정을 살펴보면 다음과 같다. 데이터를 전송(송신)하는 쪽은 상위 계층에서 하위 계층으로 데이터를 전달한다. 데이터를 받는(수신) 쪽은 하위 계층에서 상위 계층으로 각 계층을 통해 전달된 데이터를 받게 된다. 이 때, 각 계층은 독립적이므로 데이터가 전달되는 동안에 다른 계층의 영향을 받지 않는다. 

 

 

 


 

   캡슐화와 역캡슐화   

 

 데이터를 송수신 할 때에 주의할 점이 있다. 데이터를 보내려면 데이터의 앞 부분에 필요한 정보를 붙여 다음 계층으로 보내야 하는데, 이 정보를 헤더라고 한다. (1장에서 패킷은 헤더, 데이터, 트레일러로 이루어져 있다고 했는데, 그 헤더를 말한다.) 헤더에는 데이터를 전달받을 상대방에 대한 정보도 포함되어 있어야 한다. 즉, 헤더는 데이터의 내용이나 성격을 식별 또는 제어하는 데 사용한다. 

 

 

 이처럼 데이터를 전송하는 쪽에서 상위 계층의 통신 프로토콜 정보를 헤더에 담아 데이터에 붙여 나가는 것캡슐화(encapsulation)이라고 하고 데이터를 받는 쪽에서 헤더를 제거하는 것을 역캡슐화(decapsulation)라고 한다.

 

 

 

 송신 측에서 웹 사이트에 접속하려고 한다고 가정해본다.

 

 [캡슐화]

 

     1. ①과 같이 응용 계층에서는 웹 사이트를 접속하기 위한 요청 데이터가 만들어 진다. 

     2. ②와 같이 전송 계층에 전달 된다. 이 때, 신뢰할 수 있는 통신이 이루어지도록 데이터에 헤더를 붙인다.

     3. ③과 같이 전송 계층에서 만들어진 데이터를 다른 네트워크와 통신하기 위해 헤더를 붙인다.

     4. ④와 같이 네트워크 계층에서 만들어진 데이터를 물리적 통신 채널을 연결하고 통신하기 위해 헤더와 트레일러를 붙인다.

         데이터 링크 계층에서 만들어진 데이터는 최종적으로 전기 신호로 변환돼서 수신 측에 도착한다. 

 

 [역캡슐화]

 

     5. ⑥과 같이 데이터 링크 계층의 헤더와 트레일러를 제거하고 데이터를 전달한다. 

     6. ⑦~⑨와 같이 각 계층의 헤더를 제거하면서 수신 측으로 데이터를 전달한다. 

 

 

 이와 같이 데이터 한 개를 전달하는 데에 네트워크 통신의 내부에서는 여러 규칙을 통해 문제 없이 데이터를 전달해야 한다.

   1.  입출력 속도 향상  

 

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

int main() {

    ios_base::sync_with_stdio(false);
    int s, i;
    cin >> s;
    
    vector<int> v(n);
    
    for(i=0; i<n; i++) {
    	cin >> v[n];
    }
    
    for(i=0; i<n; i++) {
    	cout << v[n] << endl;
    }
	return 0;
}

 

  위 코드에서 7번째 줄에 해당하는 ios_base::sync_with_stdio(false); 를 주목해야 한다. 입력과 출력을 할 때에는 버퍼를 사용하는데 ios_base::sync_with_stdio(false);를 사용하지 않는다면 동기화 되어 있다고 표현을 하는데 이는 C++ 표준 스트림과 C 표준 스트림을 병행해서 쓸 수 있다는 것을 말한다. 이렇게 병행해서 사용하면 속도가 느려지게 된다. 

 

 따라서, ios_base::sync_with_stdio(false); 이 문장은 동기화를 하지 않겠다고 선언하는 것이며 이는 C++ 표준 스트리만 사용하겠다는 것이 된다. 따라서, 위 문장이 선언된 프로그램은 독립된 버퍼만을 사용하므로 속도적 측면에서 개선될 수 있다.

 

 속도 비교를 해보면 다음과 같다. 이는 첫째 줄에 정수의 개수 N (= 10,000,000), 둘째 줄부터 N개의 줄에 한 개의 자연수(10,000 이하)가 적힌 파일을 입력받는데 걸리는 시간을 측정한 것이다.

 

 


   2. 만능 헤더 파일   

 

//#include <iostream>
//#include <vector>

#include <bits/stdc++.h> 
using namespace std;

int main() {

    ios_base::sync_with_stdio(false);
    int s, i;
    cin >> s;
    
    vector<int> v(n);
    
    for(i=0; i<n; i++) {
    	cin >> v[n];
    }
    
    for(i=0; i<n; i++) {
    	cout << v[n] << endl;
    }
	return 0;
}

 

 매번 프로그래밍을 할 때 필요한 헤더를 선언하는 것은 불편한 일이다. 하지만, 위의 코드 처럼 bits/stdc++.h 헤더를 하나만 선언하고 cin, cout 같은 입출력 객체와 vector 컨테이너를 맘대로 쓸 수있는 방법이 존재했다. 

 

 bits/stdc++.h 헤더란 표준 라이브러리를 모두 포함하고 있는 헤더이다. 하지만  이 헤더는 GCC 전용 라이브러리이므로 GCC를 지원하는 대회 환경에서 사용해야 한다. 다행히도 대부분의 프로그래밍 환경에서는 이를 지원한다.

 

 이렇게 편리하데 단점은 없을까? 결론부터 말하자면 단점이 존재한다. 먼저 이 헤더는 위에서 언급한 것처럼 GCC가 아닌 다른 컴파일러로 코드를 컴파일 할 경우에는 실패한다. 또한, 불필요한 헤더를 많이 포함하므로 컴파일 하는데 시간이 길어진다. 마지막으로는 이식성이 떨어진다. 이식성이란 특정 환경에서 동작하는 SW 프로그램이 다른 환경으로 변경해도 동작할 수 있는 성질을 말한다.

 

 Dev C++에서도 바로 사용할 수는 없고 컴파일러 설정을 해야한다. 맨 위에서 [도구] - [컴파일러 설정]을 누르고 빨간색으로 표시된 부분에 -std=c++11을 추가한다.

 

 

 

 

 

[참고]

 

www.acmicpc.net/blog/view/56

 

입력 속도 비교

여러가지 언어와 입력 방법을 이용해서 시간이 얼마나 걸리는지 비교해 보았습니다. 방법: 첫째 줄에 정수의 개수 N (= 10,000,000), 둘째 줄부터 N개의 줄에 한 개의 자연수(10,000 이하)가 적힌 파일��

www.acmicpc.net

www.acmicpc.net/blog/view/57

 

출력 속도 비교

여러가지 언어와 출력 방법을 이용해서 시간이 얼마나 걸리는지 비교해 보았습니다. 방법: 총 N개의 줄에 1부터 10,000,000까지의 자연수를 한 줄에 하나씩 출력하는 시간을 측정. 10번 측정해서 평�

www.acmicpc.net