How We Coding

[RUNNINGMEDIAN] 변화하는 중간 값 : https://algospot.com/judge/problem/read/RUNNINGMEDIAN


### 우선순위 큐 (힙) ###


<소스코드>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
 
typedef long long int lli;
const lli MOD = 20090711LL; 
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n, b;
        lli a;
        scanf("%d%lld%d"&n, &a, &b);
 
        lli ai = 1983LL;
        lli ans = ai;
        priority_queue<lli> minH, maxH;
        maxH.push(ai);
        for(int i=1; i<n; i++) {
            ai = (1LL*ai*a+b)%MOD; 
            
            if(i&1) minH.push(-ai);
            else maxH.push(ai);
           
            if(-minH.top() < maxH.top()) {
                int a = maxH.top(); maxH.pop();
                int b = -minH.top(); minH.pop();
                maxH.push(b);
                minH.push(-a);
            }
            ans = (ans + maxH.top()) % MOD;
       }
        printf("%lld\n", ans);
    }
    return 0;
}
 
cs


>> 맥스힙에는 중간값 기준으로 중간값 포함, 그보다 작은 것들을, 민힙에는 중간값보다 큰 녀석들이 들어가게 된다. 


'PS > 종만북' 카테고리의 다른 글

[DICTIONARY] 고대어 사전  (0) 2018.05.22
[BOGGLE] 보글게임  (0) 2018.04.30
[MATCHORDER] 출전 순서 정하기  (0) 2018.04.20
[NUMBERGAME] 숫자게임  (0) 2018.04.17
[POLY] 폴리오미노  (0) 2018.04.16

[DICTIONARY] 고대어 사전 : https://algospot.com/judge/problem/read/DICTIONARY


### 위상정렬 ###



<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
using namespace std;
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        scanf("%d"&n);
        
        vector<string> v;
        for(int i=0; i<n; i++) {
            string s;
            cin >> s;
            v.push_back(s);
        }
 
        int ind[26]={0};
        vector<int> g[26];
        for(int i=1; i<n; i++) {
            int idx=0;
            while(v[i-1][idx] != 0 && v[i][idx] != 0) {
                if(v[i-1][idx] == v[i][idx]) idx++;
                else break;
            }
 
            if(v[i-1][idx] != 0 && v[i][idx] != 0) {
                g[v[i-1][idx]-'a'].push_back(v[i][idx]-'a');
                ind[v[i][idx]-'a']++;
            }
        }
 
        queue<int> q;
        for(int i=0; i<26; i++) {
            if(!ind[i])
                q.push(i);
        }
 
        vector<char> ans;
        while(!q.empty()) {
            int cur = q.front(); q.pop();
            ans.push_back('a'+cur);
            
            for(int i=0; i<g[cur].size(); i++) {
                int next = g[cur][i];
                ind[next]--;
                if(!ind[next]) {
                    q.push(next);
                }
            }
        }
        
        if(ans.size() != 26) puts("INVALID HYPOTHESIS");
        else {
            for(int i=0; i<ans.size(); i++)
                printf("%c", ans[i]);
            puts("");
        }
    }
    return 0;
}
cs



<예전에 AC 받은 코드> - 코드를 보면 종만북 솔루션으로 있는 코드같아 보인다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<int> order;
vector<bool> visited;
vector<vector<int> > v;
 
void makeGraph(const vector<string> &words)
{
    v = vector<vector<int> >(26vector<int>(260));
    for(int i=1; i<words.size(); i++) {
        int len = min(words[i-1].size(), words[i].size());
        for(int k=0; k<len; k++) {
            int a = words[i-1][k]-'a';
            int b = words[i][k]-'a';
            if(a != b) {
                v[a][b] = 1;
                break;
            }
        }
    }
}
 
void dfs(int s)
{
    visited[s] = 1;
    for(int i=0; i<v.size(); i++)
        if(v[s][i] && !visited[i])
            dfs(i);
    order.push_back(s);
}
 
vector<int> topologicalSort() {
    int i, j, n=v.size();
    visited = vector<bool>(n, 0);
    
    order.clear();
    for(i=0; i<n; i++)
        if(!visited[i])
            dfs(i);
    reverse(order.begin(), order.end());
    
    for(i=0; i<n; i++)
        for(j=i+1; j<n; j++)
            if(v[order[j]][order[i]])
                return vector<int>();
    return order;
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        vector<string> words;
 
        scanf("%d"&n);
        while(n--) {
            string s;
            cin >> s;
            words.push_back(s);
        }
 
        makeGraph(words);
        vector<int> ans = topologicalSort();
 
        n = ans.size();
        if(!n)
            puts("INVALID HYPOTHESIS");
        else {
            for(int i=0; i<n; i++) {
                printf("%c", ans[i]+'a');
            }
            puts("");
        }
    }
 
}
cs


'PS > 종만북' 카테고리의 다른 글

[RUNNINGMEDIAN] 변화하는 중간 값  (0) 2018.07.20
[BOGGLE] 보글게임  (0) 2018.04.30
[MATCHORDER] 출전 순서 정하기  (0) 2018.04.20
[NUMBERGAME] 숫자게임  (0) 2018.04.17
[POLY] 폴리오미노  (0) 2018.04.16

[BOGGLE] 보글 게임 : https://algospot.com/judge/problem/read/BOGGLE?c=16921



### DP ###


check(i, j, word) : (i, j) 에서 문자열 word 를 만들수 있는지. 


<소스코드>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
 
char boggle[5][6];
int di[]={110-1-1-101};
int dj[]={01110-1-1-1};
 
int sNum = 1;
map<stringint> msi;
int d[5][5][10000];
 
int check(int curI, int curJ, char *word)
{
    if(*(word+1== 0return true;
 
    int num;
    if(msi.find(word) == msi.end()) {
        msi[word] = sNum;
        num = sNum++;
    }
    else num = msi[word];
    
    int &ret = d[curI][curJ][num];
    if(ret != 0return ret;
 
    for(int k=0; k<8; k++) {
        int nextI = curI+di[k];
        int nextJ = curJ+dj[k];
        if((0 <= nextI && nextI < 5&& (0 <= nextJ && nextJ < 5)) {
            if(boggle[nextI][nextJ] == *(word+1&& check(nextI, nextJ, word+1== 1)
                return ret = 1;
        }
    }
    return ret = -1;
}
 
bool BOGGLE(char *word)
{
    for(int i=0; i<5; i++)
        for(int j=0; j<5; j++)
            if(boggle[i][j] == *word && check(i, j, word) == 1)
                return true;
    return false;
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        for(int i=0; i<5; i++)
            scanf("%s", boggle[i]);
        
        memset(d, 0sizeof(d));
 
        int n;
        scanf("%d"&n);
        while(n--) {
            char word[11];
            scanf("%s", word);
            printf("%s ", word);
            BOGGLE(word) ? puts("YES") : puts("NO");
        }
    }
}    
cs


>> 완전 탐색으로 소개되는 문제지만, 시간초과가 난다.

>> 해결방법은 DP 라는데... 

>> 문자열을 메모이제이션 할 방법이 도무지 떠오르질 않아 푸는데 오래 걸렸던 문제..!! >> 해싱으로 처리하였다. 

'PS > 종만북' 카테고리의 다른 글

[RUNNINGMEDIAN] 변화하는 중간 값  (0) 2018.07.20
[DICTIONARY] 고대어 사전  (0) 2018.05.22
[MATCHORDER] 출전 순서 정하기  (0) 2018.04.20
[NUMBERGAME] 숫자게임  (0) 2018.04.17
[POLY] 폴리오미노  (0) 2018.04.16

[MATCHORDER] 출전 순서 정하기 : https://algospot.com/judge/problem/read/MATCHORDER



### Greedy ###


< 소스코드 >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <cstdio>
#include <algorithm>
using namespace std;
 
int Rus[101], Kor[101];
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        scanf("%d"&n);
 
        for(int i=0; i<n; i++
            scanf("%d", Rus+i);
 
        for(int i=0; i<n; i++
            scanf("%d", Kor+i);
 
        sort(Rus, Rus+n);
        sort(Kor, Kor+n);
        
        int ri=0, ki=0;
        int ans=0;
 
        while(ri < n && ki < n) {
            if(Rus[ri] <= Kor[ki]) {
                ans++; ri++; ki++;
            }
            else ki++;
        }
        printf("%d\n", ans);
    }
}
cs


>> 차이가 최소가 되도록, 각각 오름차순 정렬 후 Korea 가 같거나 크면 이기고,

>> 러시아가 크면 다음으로 큰 한국 점수가 나올때까지 인덱스를 증가시킨다.

'PS > 종만북' 카테고리의 다른 글

[DICTIONARY] 고대어 사전  (0) 2018.05.22
[BOGGLE] 보글게임  (0) 2018.04.30
[NUMBERGAME] 숫자게임  (0) 2018.04.17
[POLY] 폴리오미노  (0) 2018.04.16
[ASYMTILING] 비대칭 타일링  (0) 2018.04.16

[NUMBERGAME] 숫자게임 : https://algospot.com/judge/problem/read/NUMBERGAME



< 소스코드 >


gameNum(s, e) : (s, e) 까지 최선을 다해 게임을 했을 때, 서하점수-현우점수의 최대값.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <string.h>
 
const int INF = 1e9;
 
int a[51];
int d[51][51];
 
int max(int a, int b)
{
    return a > b ? a : b;
}
 
int gameNum(int s, int e)
{
    int ret=0;
    if(s == e) return a[s];
    if(s > e) return 0;
    if(d[s][e] != INF) return d[s][e];
 
    ret = max(a[s]-gameNum(s+1, e), a[e]-gameNum(s, e-1));
    if(e->= 1) ret = max(ret, -gameNum(s+2, e));
    if(e->= 1) ret = max(ret, -gameNum(s, e-2));
 
    return d[s][e] = ret;
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        scanf("%d"&n);
 
        for(int i=0; i<n; i++) {
            scanf("%d", a+i);
            for(int j=0; j<n; j++
                d[i][j] = INF;
        }
 
        
        printf("%d\n", gameNum(0, n-1));
    }
    return 0;
}
 
cs


>> 재귀적으로 함수를 호출하는 과정에서 음수처리 한 부분에 주목.

>> 현우부터 게임을 시작하고, 현우가 서하보다 몇점을 더 얻을수 있는지 알아야 하기에..

>> 첫번째 턴에서 현우가 가진 점수는 그대로 현우의 점수가 된다. 두번째 턴에서 서하가 가진 점수는 현우의 점수에서 빼주면 그것이 그대로 차이가 된다.

'PS > 종만북' 카테고리의 다른 글

[BOGGLE] 보글게임  (0) 2018.04.30
[MATCHORDER] 출전 순서 정하기  (0) 2018.04.20
[POLY] 폴리오미노  (0) 2018.04.16
[ASYMTILING] 비대칭 타일링  (0) 2018.04.16
[TRIPATHCNT] 삼각형 위의 최대 경로 수 세기  (0) 2018.04.15

[POLY] 폴리오미노 : https://algospot.com/judge/problem/read/POLY



### DP ###


< 소스코드 >


poly(up, n) : 윗층에 up개의 블럭이 쌓여있을 때, n 개로 폴리오미노를 만들 수 있는 방법의 수.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
 
const int MOD = 10000000;
 
int d[101][101];
 
int poly(int up, int n)
{
    int ret = 0;
    if(n == 0return 1;
    if(n == 1return up;
    if(d[up][n]) return d[up][n];
 
    for(int down=1; down<=n; down++) {
        ret += (poly(down, n-down)*(up+down-1));
        ret %= MOD;
    }
    return d[up][n] = ret; 
}   
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n, ans=0;
        scanf("%d"&n);
 
        for(int i=1; i<=n; i++) {
            ans += poly(i, n-i);
            ans %= MOD;
        }
        printf("%d\n", ans);
    }
     
    return 0;
}
cs


>> 15 : 곱해줘야하는데, 더해서 시간을 많이 소비했다....

'PS > 종만북' 카테고리의 다른 글

[MATCHORDER] 출전 순서 정하기  (0) 2018.04.20
[NUMBERGAME] 숫자게임  (0) 2018.04.17
[ASYMTILING] 비대칭 타일링  (0) 2018.04.16
[TRIPATHCNT] 삼각형 위의 최대 경로 수 세기  (0) 2018.04.15
[TILING2] 타일링  (0) 2018.04.15

[ASYMTILING] 비대칭 타일링 : https://algospot.com/judge/problem/read/ASYMTILING


### DP ###


< 소스코드 >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
 
const int MOD = 1000000007;
 
int d[101];
 
int tiling(int n)
{
    if(n <= 1return 1;
    if(d[n]) return d[n];
    return d[n] = (tiling(n-1+ tiling(n-2)) % MOD;
}
 
int asymtiling(int n)
{
    int ret;
    ret = tiling(n/2) % MOD;
    if(n&1return ret;
    ret += ((tiling((n/2)-1)) % MOD);
    return ret%MOD;
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        scanf("%d"&n);
        printf("%d\n", (tiling(n)-asymtiling(n)+MOD)%MOD);
    }
    return 0;
}
cs


>> 전체 경우의 수에서 대칭적으로 만들수 있는 타일링의 갯수를 빼면 된다.

'PS > 종만북' 카테고리의 다른 글

[NUMBERGAME] 숫자게임  (0) 2018.04.17
[POLY] 폴리오미노  (0) 2018.04.16
[TRIPATHCNT] 삼각형 위의 최대 경로 수 세기  (0) 2018.04.15
[TILING2] 타일링  (0) 2018.04.15
[PI] 원주율 외우기  (0) 2018.04.15

[TRIPATHCNT] 삼각형 위의 최대 경로 수 세기 : https://algospot.com/judge/problem/read/TRIPATHCNT



### DP ###


< 소스코드 >


PathCnt(r, c) : (r, c) 좌표에서 시작하는 삼각형 위의 최대 경로 후.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <string.h>
 
int n;
int a[101][101];
int d[101][101], e[101][101];
 
int max(int a, int b)
{
    return a > b ? a : b;
}
 
int PathSum(int r, int c)
{
    int ret;
    if(!a[r][c]) return 0;
    if(r == n) return a[r][c];
    if(e[r][c]) return e[r][c];
    
    ret = max(PathSum(r+1, c), PathSum(r+1, c+1));
    return e[r][c] = ret + a[r][c];
}
 
int PathCnt(int r, int c)
{   
    int ret=0;
    int a, b;
    if(r == n) return 1;
    if(d[r][c]) return d[r][c];
 
    a = PathSum(r+1, c);
    b = PathSum(r+1, c+1);
    if(a == b) ret += (PathCnt(r+1, c) + PathCnt(r+1, c+1));
    else ret += (a > b ? PathCnt(r+1, c) : PathCnt(r+1, c+1));
 
    return d[r][c] = ret; 
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        scanf("%d"&n);
 
        for(int i=1; i<=n; i++)
            for(int j=1; j<=i; j++)
                scanf("%d"&a[i][j]);
        
        memset(d, 0sizeof(d));
        memset(e, 0sizeof(e));
        printf("%d\n", PathCnt(11));
    }
    return 0;
}
cs


>> 일단 삼각형 위의 최대값을 구한 다음에 갯수를 세야한다.

>> 다음으로 위치에서 시작하는 삼각형위의 최대값이 최대일 때, 갯수에 포함시켜야 한다. 같다면 둘다 포함시킨다.

'PS > 종만북' 카테고리의 다른 글

[POLY] 폴리오미노  (0) 2018.04.16
[ASYMTILING] 비대칭 타일링  (0) 2018.04.16
[TILING2] 타일링  (0) 2018.04.15
[PI] 원주율 외우기  (0) 2018.04.15
[LIS] 최대 증가 부분 수열  (0) 2018.04.13

[TILING2] 타일링

PS/종만북2018. 4. 15. 00:53

[TILING2] 타일링 : https://algospot.com/judge/problem/read/TILING2



< 소스코드 > 


tiling(n) : 2 x n 크기의 사각형을 2 x 1 의 타일로 채우는 경우의 수.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#define MOD 1000000007
 
int d[101];
 
int tiling2(int n)
{
    if(n == 0return 1;
    if(n < 0return 0;
    if(d[n]) return d[n];
    
    return d[n] = (tiling2(n-1+ tiling2(n-2)) % MOD;
}
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        int n;
        scanf("%d"&n);
        printf("%d\n", tiling2(n));
    }   
    
    return 0;
}
cs

>> 2 x 1 하나를 채우고 나면 2 x n-1 크기를 채우면 된다.

>> 1 x 2 두개를 = 이렇게 채우고 나면, 2 x n-2 크기를 채우면 된다. 


[PI] 원주율 외우기 : https://algospot.com/judge/problem/read/PI

 


### DP ###


< 소스코드 >


pi(i) : i 번째 인덱스에서 시작하는 난이도의 최소 합.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <stdio.h>
#include <string.h>
#define INF 1e9
 
char p[10001];
int len, d[10001];
 
int min(int a, int b)
{
    return a < b ? a : b;
}
 
int isSame(int s, int cnt)
{
    for(int i=s; i<s+cnt-1; i++)
        if(p[i] != p[i+1]) 
            return 0;
    return 1;
}
 
int isInc(int s, int cnt)
{
    for(int i=s; i<s+cnt-1; i++)
       if(p[i]+1 != p[i+1])
           return 0;
    return 1;
}
 
int isDec(int s, int cnt)
{
    for(int i=s; i<s+cnt-1; i++)
        if(p[i]-1 != p[i+1])
            return 0;
    return 1;
}
 
int isAlter(int s, int cnt)
{
    if(cnt == 3) {
        if(p[s] == p[s+2]) return 1;
    }
    else if(cnt == 4) {
        if(p[s] == p[s+2&& p[s+1== p[s+3]) return 1;
    }
    else if(cnt == 5) {
        if(p[s] == p[s+2&& p[s+2== p[s+4&& p[s+1== p[s+3])
            return 1;
    }
    return 0;
}
 
int isSeq(int s, int cnt)
{
    int diff = p[s+1- p[s];
    for(int i=s; i<s+cnt-1; i++)
        if(p[i]+diff != p[i+1])
            return 0;
    return 1;
}
    
 
int getScore(int s, int cnt)
{
    if(isSame(s, cnt)) return 1;
    if(isInc(s, cnt) || isDec(s, cnt)) return 2;
    if(isAlter(s, cnt)) return 4;
    if(isSeq(s, cnt)) return 5;
    return 10;
}
 
 
int pi(int s)
{
    int k, ret = INF;
    if(s == len) return 0;
    if(s > len) return INF;
    if(d[s]) return d[s];
 
    for(int i=3; i<=5; i++) {
        k = getScore(s, i);
        ret = min(ret, pi(s+i)+k);
    }
 
    return d[s] = ret;
}
 
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while(tc--) {
        scanf("%s", p);
    
        len = strlen(p);
        memset(d, 0sizeof(d));
 
        printf("%d\n", pi(0)); 
    }
    return 0;
}
 
cs


>> isSame() 등의 함수에서 for 문의 조건식을 s+cnt-1 로 해야했는데, 계속 cnt-1 로 해서 시간을 많이 소비했다..ㅜ

'PS > 종만북' 카테고리의 다른 글

[TRIPATHCNT] 삼각형 위의 최대 경로 수 세기  (0) 2018.04.15
[TILING2] 타일링  (0) 2018.04.15
[LIS] 최대 증가 부분 수열  (0) 2018.04.13
[TRIANGLEPATH] 삼각형 위의 최대경로  (0) 2018.04.10
[PICNIC] 소풍  (0) 2018.04.09