while(v!= NULL) { printf("%c : ", v->Data); if ((e = v->AdjacencyList) == NULL) { v = v->next; printf("\n"); continue; }
while(e != NULL) { printf("%c[%d] ", e->target->Data, e->weight); e = e->next; } printf("\n"); v = v->next; } printf("\n"); }
그래프 탐색 방법
1. 깊이 우선 탐색 (Depth First Search : DFS)
더 나아갈 길이 보이지 않을 때까지 깊이 들어간다.
한 방향으로 계속 가다가 더 이상 갈수 없게 되면 다시 가장 가까운 갈림길로 돌아와서 다른 방향으로 탐색을 진행
길이 나오지 않을 때까지 그래프의 정점을 타고 깊이 들어가다 더 이상 방문해왔던 정점말고는 다른 이웃을 갖고 있지 않은 정점을 만나면 뒤로 돌아와 다른 경로로 뻗어 있는 정점을 타고 방문을 재개하는 방식
DFS 알고리즘
시작 정점을 밟은 후 이 정점을 ‘방문했음’으로 표시
이 정점과 이웃하고 있는 정점(인접정점)중에서 아직 방문하지 않은 곳을 선택하고 이를 시작 정점으로 삼아 다시 깊이 우선탐색을 시작(1단계를 다시하는 것)
정점에 더 이상 방문하지 않은 인접 정점이 없으면 이전 정점으로 돌아가서 2단계를 수행
이전 정점으로 돌아가도 더 이상 방문할 이웃이 없으면 그래프의 모든 정점을 방문했으므로 탐색을 종료
1 2 3 4 5 6
//u 아직방문하지 않은 정점 depth_first_search(v) v를 방문했다고 표시 for v에 인접한 정점 탐색 do if (탐색하지 못한 정점이 있다면) then depth_first_search(u)
DFS 소스코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14
voidDFS(Vertex* v) { //1. 이미 방문햇음을 표시 Edge* e = NULL; printf("%d ", v->data); v->visited = visited; //이미 방문했다는 것을 표시 e = v->adjacencyList; //인접한 정점 리스트 while(e != NULL) { // 현재 정점의 모든 인접정점에 대해 DFS를 재귀적으로 호출 if (e->target != NULL && e->target->Visited == NotVisited) { //인접데이터가 방문하지 않았으면 재귀호출 DFS(e->target); } e = e->next; } }
2. 너비 우선 탐색 (Breadth First Search : BFS)
시작 정점부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회방법
너비 우선 탐색을 하기 위해서 방문한 정점들을 차례로 저장하고 꺼낼 수 있는 Queue가 필요
정점이 방문될 때마다 큐에 방문한 정점을 삽입하고 더이상 방문할 인접 정점이 없는 경우 큐 앞에서 정점을 꺼내어 그 정점과 인접한 정점들을 차례대로 방문
BFS 알고리즘
시작 정점을 ‘방문했음’으로 표시 하고 큐에 삽입
큐로부터 정점을 제거(dequeue)하고 제거한 정점이 이웃하고 있는 인접 정점 중 아직 방문하지 않은 곳들을 ‘방문했음’으로 표시하고 큐에 삽입
큐가 비게 되면 탐색이 끝난 것이고 큐가 빌때까지 2를 반복
1 2 3 4 5 6 7 8 9 10
//u 방문하지 않은 정점 breadth_first_search(v) v를 방문되었다고 표시; queue <- v; //큐에 정점 v 삽입 while (not isempty(queue)) do queue에서 정점 w를 삭제 for 인접정점 탐색 do if (아직 방문되지 않은 정점이 있다면) then u를 큐에 삽입 방문되었다고 표시
publicclassMain{ publicstaticvoidmain(String[] args){ Scanner scan = new Scanner(System.in); int[] a = newint[9]; int sum = 0; for (int i = 0; i < 9; i++) { a[i] = scan.nextInt(); sum += a[i]; } int[] result = dwarfOf7(a, sum); if (result == null) { return; } Arrays.sort(result); for (int i = 2 ;i <result.length; i++) { System.out.println(result[i]);
} }
publicstaticint[] dwarfOf7(int a[], int sum) { for (int i =0 ; i < 9; i++) { for (int j = i + 1; j < 9; j++) { if (sum - (a[i] + a[j]) == 100) { a[i] = a[j] = -1; return a; } } } returnnull; } }
publicstaticvoidmain(String[] args)throws Exception { BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine()); out.write("" + easyStair(n)); out.write("\n"); out.flush(); out.close(); in.close(); }
publicstaticlongeasyStair(int n){ long mod = 1000000000L; long[][] dp = newlong[n + 1][10]; for (int i = 1; i <= 9; i++) { dp[1][i] = 1; } for (int i = 2; i <= n; i++) { for (int j = 0; j <= 9; j++) { dp[i][j] = 0; if (j - 1 >= 0) { dp[i][j] += dp[i - 1][j - 1]; } if (j + 1 <= 9) { dp[i][j] += dp[i - 1][j + 1]; } dp[i][j] %= mod; } } long solv = 0; for (int i = 0; i <=9; i++) { solv += dp[n][i]; } return solv %= mod; } }
Posted onInComputer
,
CodingTestDisqus: Symbols count in article: 2.1kReading time ≈2 mins.
카드 구매하기
문제
요즘 민규네 동네에서는 스타트링크에서 만든 PS카드를 모으는 것이 유행이다.
PS카드는 PS(Problem Solving)분야에서 유명한 사람들의 아이디와 얼굴이 적혀있는 카드이다. 각각의 카드에는 등급을 나타내는 색이 칠해져 있고, 다음과 같이 8가지가 있다.
전설카드 레드카드 오렌지카드 퍼플카드 블루카드 청록카드 그린카드 그레이카드
카드는 카드팩의 형태로만 구매할 수 있고, 카드팩의 종류는 카드 1개가 포함된 카드팩, 카드 2개가 포함된 카드팩, … 카드 N개가 포함된 카드팩과 같이 총 N가지가 존재한다.
민규는 카드의 개수가 적은 팩이더라도 가격이 비싸면 높은 등급의 카드가 많이 들어있을 것이라는 미신을 믿고 있다. 따라서, 민규는 돈을 최대한 많이 지불해서 카드 N개 구매하려고 한다. 카드가 i개 포함된 카드팩의 가격은 Pi원이다.
예를 들어, 카드팩이 총 4가지 종류가 있고, P1 = 1, P2 = 5, P3 = 6, P4 = 7인 경우에 민규가 카드 4개를 갖기 위해 지불해야 하는 금액의 최댓값은 10원이다. 2개 들어있는 카드팩을 2번 사면 된다.
P1 = 5, P2 = 2, P3 = 8, P4 = 10인 경우에는 카드가 1개 들어있는 카드팩을 4번 사면 20원이고, 이 경우가 민규가 지불해야 하는 금액의 최댓값이다.
마지막으로, P1 = 3, P2 = 5, P3 = 15, P4 = 16인 경우에는 3개 들어있는 카드팩과 1개 들어있는 카드팩을 구매해 18원을 지불하는 것이 최댓값이다.
카드 팩의 가격이 주어졌을 때, N개의 카드를 구매하기 위해 민규가 지불해야 하는 금액의 최댓값을 구하는 프로그램을 작성하시오. N개보다 많은 개수의 카드를 산 다음, 나머지 카드를 버려서 N개를 만드는 것은 불가능하다. 즉, 구매한 카드팩에 포함되어 있는 카드 개수의 합은 N과 같아야 한다.
입력
첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다. (1 ≤ N ≤ 1,000)
publicstaticvoidmain(String[] args)throws Exception { BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine()); String[] ar = in.readLine().split(" "); int[] p = newint[n+1]; for (int i = 1; i<=n; i++) { p[i] = Integer.parseInt(ar[i-1]); } out.write("" + cardBuy(p, n)); out.write("\n"); out.flush(); out.close(); in.close(); }
publicstaticintcardBuy(int[] p, int n){ int[] dp = newint[n + 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { dp[i] = Math.max(dp[i], dp[i - j] + p[j]); } } return dp[n]; } // 카드구매하기 2 //https://www.acmicpc.net/problem/16194 publicstaticintcardBuy2(int[] p, int n){ int[] dp = newint[n + 1]; for (int i = 1; i <= n; i++) { dp[i] = -1; for (int j = 1; j <= i; j++) { if (dp[i] == -1 || dp[i] > dp[i-j] + p[j]) { dp[i] = dp[i-j] + p[j]; } } } return dp[n]; } }