구글 코드잼 2009 Qualification Round 풀이

안녕하세요. Astein 입니다.

회사에 아침 8시에 출근해서 GCJ Qual을 했는데, 세팅이 제대로 안되서... ㅜㅜ

12등이라는 성적을 거두긴 했는데, 10등 안에 못들어서 아쉽네요 :(

-------------------------------------------------------------------------

A. Alien Language

  외계어는 L개의 소문자로 이루어진 단어 D개가 있다. N개의 패턴이 주어졌을 때, 각각의 패턴에 해당하는 단어가 몇개씩
있는지 구하는 프로그램을 작성하시오. 패턴의 각 글자는 소문자거나 괄호로 둘러쌓여진 소문자들의 그룹으로 이루어져 있다. 예를 들어 (ab)d(dc) 같은 경우, 첫 글자는 a 또는 b, 두번째 글자는 d, 세번째 글자는 d 또는 c인 단어를 의미하며, add, adc, bdd, bdc 의 4가지 가능성이 있다.

B. Watersheds

  높이가 표시된 지도가 있다. 어떤 위치에 비가 오는 경우, 빗물은 특정한 조건에 따라 흐른다.

  1. 각 칸에서 빗물은 인접한 4개의 칸으로만 흐른다
  2. 각각의 칸에 대해서, 현재 위치보다 낮은 곳이 주변에 없는 경우, 물은 흐르지 않고, 현재의 칸은 sink가된다.
  3. 그렇지 않으면 물은 인접한 칸들 중 제일 낮은 칸으로 흐른다.
  4. 만약 3번의 경우, 제일 낮은 높이의 인접한 칸이 여러 개 있는 경우, N, W, E, S의 순서대로 흐른다.

  모든 칸의 물은 직접 혹은 간접적으로 흐르게 되고, 이는 sink에서 모이게 된다. 동일한 sink에 모이는 지점들을 하나의 그룹으로
묶는다고 할 때, 그룹들을 알파벳으로 구분해 보자.

C. Welcome to Code Jam

  주어진 string에서 "welcome to code jam"을 만들 수 있는 조합의 경우의 수를 출력하여라. 단 10000으로 나눈 나머지를 구하시오




A. 간단한 패턴 매칭 문제입니다. 입력받은 패턴과 같은 단어가 몇 개가 있는지 찾아보면 됩니다. :)


 1 #include <cstdio>
 2 #include <vector>
 3 #include <string>
 4 #include <iostream>
 5
 6 using namespace std;
 7
 8 int check(string a, string b)
 9 {
10   int pos = 0;
11   for (int i = 0; i < b.size(); ++i)
12   {
13     string word = "";
14     if (a[pos] == '(')
15     {
16       for (int j = pos + 1; ; ++j)
17         if (a[j] == ')')
18         {
19           pos = j + 1;
20           break;
21         }
22         else word += a[j];
23
24     }
25     else 
26     {
27       word = a[pos];
28       pos++;
29     }
30
31     bool isOK = false;
32     for (int j = 0; j < word.size(); ++j)
33       if (word[j] == b[i]) isOK = true;
34     if (!isOK) return 0;
35   }
36
37   if (pos != a.size()) return 0;
38   return 1;
39 }
40
41 int main()
42 {
43   int L, D, N;
44   cin >> L >> D >> N;
45
46   vector<string> word(D);
47
48   for (int i = 0; i < D; ++i)
49     cin >> word[i];
50
51   for (int q = 0; q < N; ++q)
52   {
53     int ret = 0;
54     string str;
55
56     cin >> str;
57     for (int i = 0; i < D; ++i)
58     {
59       if (check(str, word[i])) ret++;
60     }
61     printf("Case #%d: %d\n", q + 1, ret);
62   }
63 }

B. Watersheds

  일단 주어진 지도에서 물이 어느 방향으로 흐르는지를 그래프로 나타낼 수 있습니다. 이 그래프에서 어떤 sink로 도달하는지를 찾아서 같은 sink끼리 묶어주면 됩니다. 저는 어떤 칸에서 물이 흐른다면 이를 무방향성 그래프로 만들어서 같은 그룹을 묶는 방식으로 해결하였습니다.


  1 #include <iostream>
  2 #include <queue>
  3 #include <vector>
  4 #include <cstdlib>
  5 #include <algorithm>
  6
  7 using namespace std;
  8
  9 int table[101][101];
 10 vector< int > graph[101][101];
 11 char ret[101][101];
 12 char ch;
 13
 14 int dx[4] = {-1, 0, 0, 1};
 15 int dy[4] = {0, -1, 1, 0};
 16
 17 void go(int x, int y)
 18 {
 19     queue<pair<int, int> > Q;
 20     Q.push( make_pair( x, y ));
 21
 22     ret[x][y] = ch;
 23     while (!Q.empty())
 24     {
 25         pair<int, int> now = Q.front(); Q.pop();
 26         
 27         x = now.first, y = now.second;
 28         for (int i = 0; i < graph[x][y].size(); ++i)
 29         {
 30             int nx = x + dx[ graph[x][y][i] ];
 31             int ny = y + dy[ graph[x][y][i] ];
 32
 33             if (ret[nx][ny] == '?')
 34             {
 35                 ret[nx][ny] = ch;
 36                 Q.push(make_pair( nx, ny ));
 37             }
 38         }
 39     }
 40 }
 41
 42 int main()
 43 {
 44     int T;
 45     cin >> T;
 46
 47     int n, m;
 48
 49     for (int q = 1; q <= T; ++q)
 50     {
 51         cin >> n >> m;
 52         for (int i = 0; i < n; ++i)
 53             for (int j = 0; j < m; ++j)
 54             {
 55                 cin >> table[i][j];
 56                 graph[i][j].clear();
 57                 ret[i][j] = '?';
 58             }
 59
 60         for (int i = 0; i < n; ++i)
 61         {
 62             for (int j = 0; j < m; ++j)
 63             {
 64                 bool isSink = true;
 65                 int mn = table[i][j];
 66                 int p = -1;
 67
 68                 for (int k = 0; k < 4; ++k)
 69                 {
 70                     int nx = i + dx[k], ny = j + dy[k];
 71                     if (nx < 0 || nx == n || ny < 0 || ny == m) continue;
 72                     if (table[i][j] > table[nx][ny]) isSink = false;
 73                     if (mn > table[nx][ny])
 74                     {
 75                         mn = table[nx][ny];
 76                         p = k;
 77                     }
 78                 }
 79
 80                 if (isSink) continue;
 81
 82                 graph[i][j].push_back( p );
 83                 graph[i + dx[p]][j + dy[p]].push_back( 3 - p );
 84             }
 85         }
 86
 87         ch = 'a';
 88         for (int i = 0; i < n; ++i)
 89         {
 90             for (int j = 0; j < m; ++j)
 91             {
 92                 if( ret[i][j] == '?' )
 93                 {
 94                     go(i, j);
 95                     ch++;
 96                 }
 97             }
 98         }
 99         cout << "Case #" << q << ":" << endl;
100         for (int i = 0; i < n; ++i)
101         {
102             for (int j = 0; j < m; ++j)
103                 cout << ret[i][j] << ' ';
104             cout << endl;
105         }
106     }
107     return 0;
108 }


C. Welcome to Code Jam

  전형적인 DP 문제입니다... 10000으로 나눈 나머지는 고등학교때 배우는 나머지 정리를 이용하시면 구할 수 있습니다.
 (A + B) % C = ((A % C) + (B % C)) % C



 1 #include <cstdio>
 2 #include <iostream>
 3 #include <sstream>
 4
 5 using namespace std;
 6
 7 int T;
 8 string s = "welcome to code jam";
 9 int table[505][25];
10
11 int main()
12 {
13   string str;
14   char tmp[1005];
15
16   fgets(tmp, 1000, stdin); str = tmp;
17   istringstream sin(str); sin >> T;
18   
19   for (int Q = 1; Q <= T; ++Q)
20   {
21     fgets(tmp, 1000, stdin); str = tmp;
22     memset(table, 0, sizeof(table));
23
24     for (int i = 0; i < str.size(); ++i)
25     {
26       for (int j = 0; j < s.size(); ++j)
27       {
28         if (i != 0) table[i][j] = table[i - 1][j];
29         if (str[i] == s[j])
30         {
31           if (j == 0) table[i][j]++;
32           else if (i > 0) table[i][j] += table[i - 1][j - 1];
33         }
34         table[i][j] %= 10000;
35       }
36     }
37
38     printf("Case #%d: %04d\n", Q, table[str.size() - 1][s.size() - 1]);
39   }
40 }


혹시 궁금하신 점이 있으시면 언제라도 댓글 환영합니다. :D

이 글과 관련있는 글을 자동검색한 결과입니다 [?]

by 아스탱 | 2009/09/07 02:07 | 프로그래밍 이야기 | 트랙백 | 덧글(12)

트랙백 주소 : http://astein.egloos.com/tb/4228588
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by soyoja at 2009/09/08 17:00
감사합니다... ^^
Commented by JM at 2009/09/08 22:00
알고스팟에도 올려주세여 (1)
Commented by Xhark at 2009/09/08 23:31
광고보고 왔슈니다!!!><
Commented by rubyeye at 2009/09/09 02:08
광고 맞구만 모 -_-
Commented by Toivoa at 2009/09/09 06:49
광고보고 왔음 -_-b
Commented by legend12 at 2009/09/10 22:43
광고쟁이
Commented by Kogle at 2009/09/11 04:00
광고 보고 왔음~ㅋ
Commented by i274 at 2009/09/12 12:38
알고스팟에도 올려주세요 ㅎㅎ
Commented by xhae at 2009/09/13 14:07
z...
Commented by helloneo at 2009/09/13 17:51
알고스팟 감사합니다
Commented by astein at 2009/09/14 10:29
알고스팟에 올렸어요~ ㅎㅎ
Commented by 그래요 at 2009/09/16 18:30
링크신고요

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶