문제링크) https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5P1kNKAl8DFAUq


문제는 각줄마다 문장이 입력이 되는데 그 문장에서 반복마디를 구하면된다.

-입력-

KOREAKOREAKOREAKOREAKOREAKOREA

SAMSUNGSAMSUNGSAMSUNGSAMSUNGSA

GALAXYGALAXYGALAXYGALAXYGALAXY

EXOEXOEXOEXOEXOEXOEXOEXOEXOEXO

B1A4B1A4B1A4B1A4B1A4B1A4B1A4B1

APINKAPINKAPINKAPINKAPINKAPINK

BLACKPINKBLACKPINKBLACKPINKBLA

TWICETWICETWICETWICETWICETWICE

REDVELVETREDVELVETREDVELVETRED

ABCABCABCABCABCABCABCABCABCABC

-출력-

#1 5

#2 7

#3 6

#4 3

#5 4

#6 5

#7 9

#8 5

#9 9

#10 3

이문제 핵심은 반복마디가 최소로 반복되는 길이여야 한다. 맨마지막 입력예시를 보면 abcabcabcabc라서 abc가 반복이될수도있고

abcabc가 될수도있고 abcabcabc가 반복될수도 있기에 모두 정답이 될 수 있다. 하지만 출력을 보면 이 반복되는 것들 중에서도 최소의 길이를 갖는

반복패턴을 원한 것을 알 수 있었다.


반복마디의 길이가 최대 10길이여서 

1~10까지의 반복마디를 각각 생성하고나자마자 만들어진 반복마디와 기존배열을 반복마디의 개수만큼 계속해서 비교해나가주었다.

그렇게되면 하나라도어긋나면 정답이 아니게되므로 자연스럽게 반대의 경우만이 정답이 된다.


소스코드)

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
#include<iostream>
using namespace std;
int main()
{
    int test_case;
    cin >> test_case;
    for(int t= 1; t<=test_case; t++)
    {
    
        char str[31];
        char repeat[11]; //반복 문자열 
        int cnt;
        int j;
        int ret;
        int k;
        cin >> str;
        int len; // 반복 길이 
        for(len = 1; len <= 10; len++)
        {
            cnt = 0;
            k = 0;
            for(int i = 0; i<len; i++)
            {
                repeat[i] = str[i];
            }
            
            for( j = len; j<30; j++)
            {
                if(cnt == len)
                {
                    cnt = 0;
                    k = 0;
                }
                if(repeat[k++]!= str[j])
                {
                    break;
                }
                cnt++;
            }
            if(j == 30)
            {
                ret = len;
                break;
            }
        }    
        cout <<"#"<<<<' '<< ret << '\n';
    }    
}
    
cs



반응형

'PS > SWEA' 카테고리의 다른 글

D1 1545번 거꾸로 출력해 보아요  (0) 2022.05.06
5986번 새샘이와 세 소수  (0) 2018.11.03
1859번 백만 장자 프로젝트  (0) 2018.10.13
5550번 나는 개구리로소이다  (0) 2018.10.06
1926번 간단한 369게임  (0) 2018.10.05

문제 링크 : https://www.acmicpc.net/problem/14891


해결방법)

문제를 읽고나서 생각해 봣는데 각 명령마다 순차적으로 톱뉘를 돌려나가면 되겠다라고 생각했다.

즉, 단순구현으로 풀었고(소스가 더러운느낌,..) 톱니번호와 회전방향을 가지고 있는 그대로 코드를 짜보았다.


- 알고리즘 순서 

1. 톱니 바퀴 정보를 입력받는다.

2. 각 명령을 하기 직전에 톱니들 사이의 접합부분이 맞닿았는지 혹은 떨어졌는지를 확인한다

3. 명령마다 주어진 바퀴번호와 회전방향을 보면서 해당 바퀴번호 기준으로 접합정보를 차례대로 비교해 나가면서 바퀴를 회전 시켜준다.

4. 명령이 끝날때까지 2,3번을 반복하고 반복이 끝나면 답을 구해줄 수 있다.



소스코드) 

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include<iostream>
#include<cstring>
#define LEFT 6
#define RIGHT 2
using namespace std;
int cnt_cmd;
int wheel[4][8]; // 바퀴 0, 1, 2, 3
// 0 1 2 3 4 로 0은 12시방향 
int flag[4]; // 4바퀴의 회전여부 
void Check(int wheel[][8])
{
    if (wheel[0][RIGHT] == wheel[1][LEFT])
    {
        flag[0= -1;
    }
    else
    {
        flag[0= 1;
    }
    if (wheel[1][RIGHT] == wheel[2][LEFT])
    {
        flag[1= -1;
    }
    else
    {
        flag[1= 1;
    }
    if (wheel[2][RIGHT] == wheel[3][LEFT])
    {
        flag[2= -1;
    }
    else
        flag[2= 1;
 
}
void moveLeft(int wheel[][8] , int wheelnum)
{
    int tmp = wheel[wheelnum][RIGHT];
    for (int i = 3; i <= 7; i++)
    {
        wheel[wheelnum][i - 1= wheel[wheelnum][i];
    }
    wheel[wheelnum][7= wheel[wheelnum][0];
    wheel[wheelnum][0= wheel[wheelnum][1];
    wheel[wheelnum][1= tmp;
}
void moveRight(int wheel[][8] , int wheelnum)
{
    int tmp = wheel[wheelnum][LEFT];
    for (int i = 5; i >= 0; i--)
    {
        wheel[wheelnum][i + 1= wheel[wheelnum][i];
    }
    wheel[wheelnum][0= wheel[wheelnum][7];
    wheel[wheelnum][7= tmp;
}
int main()
{
    for (int j = 0; j < 8; j++)
    {
        scanf("%1d"&wheel[0][j]);
    }
    for (int j = 0; j < 8; j++)
    {
        scanf("%1d"&wheel[1][j]);
    }
    for (int j = 0; j < 8; j++)
    {
        scanf("%1d"&wheel[2][j]);
    }
    for (int j = 0; j < 8; j++)
    {
        scanf("%1d"&wheel[3][j]);
    }
    /*for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            printf("%d ", wheel[i][j]);
        }
        puts("");
    }*/
    cin >> cnt_cmd;
    int select, dir;
    int ret = 0;
    int tmp;
    for (int i = 0; i < cnt_cmd; i++)
    {
        scanf("%d %d"&select, &dir);
        memset(flag, 0sizeof(flag));
        // 한번의 명령 마다 12시 방향값들을 더해나간다.
 
        Check(wheel);
        if (select == 1)
        {
            // 1번 바퀴일때 
            if (dir == -1)
            {
                moveLeft(wheel, 0);
                if (flag[0== 1// 다르다면 회전한다.
                {
                    //반시계일때
                    moveRight(wheel, 1);
                    if (flag[1== 1)
                    {
                        moveLeft(wheel, 2);
                        if (flag[2== 1)
                        {
                            moveRight(wheel, 3);
                        }
                    }
                }
            }
            else if (dir == 1)
            {
                //시계일때
                moveRight(wheel, 0);
                if (flag[0== 1// 다르다면 회전한다.
                {
                    moveLeft(wheel, 1);
                    if (flag[1== 1)
                    {
                        moveRight(wheel, 2);
                        if (flag[2== 1)
                        {
                            moveLeft(wheel, 3);
                        }
                    }
                }
            }
        }
        else if (select == 2)
        {
            if (dir == -1)
            {
                moveLeft(wheel, 1); // 두번째바퀴 시계반대돌리고
                if (flag[0== 1)
                {
                    moveRight(wheel, 0); // 첫번째바퀴 시계방향돌린다.
                }
                if (flag[1== 1)
                {
                    moveRight(wheel, 2);
                    if (flag[2== 1)
                    {
                        moveLeft(wheel, 3);
                    }
                }
            }
            else if (dir == 1)
            {
                moveRight(wheel, 1);
                if (flag[0== 1)
                {
                    moveLeft(wheel, 0);
                }
                if (flag[1== 1)
                {
                    moveLeft(wheel, 2);
                    if (flag[2== 1)
                    {
                        moveRight(wheel, 3);
                    }
                }
            }
        }
 
 
        else if (select == 3)
        {
            if (dir == -1)
            {
                moveLeft(wheel, 2);
                if (flag[1== 1)
                {
                    //왼쪽이 달라서 돌릴수잇다면 
                    moveRight(wheel, 1);
                    if (flag[0== 1)
                    {
                        moveLeft(wheel, 0);
                    }
                }
                if (flag[2== 1)
                {
                    moveRight(wheel, 3);
                }
            }
            else if (dir == 1)
            {
                moveRight(wheel, 2);
                if (flag[1== 1)
                {
                    moveLeft(wheel, 1);
                    if (flag[0== 1)
                    {
                        moveRight(wheel, 0);
                    }
                }
                if (flag[2== 1)
                {
                    moveLeft(wheel, 3);
                }
            }
        }
        else if (select == 4)
        {
            if (dir == -1)
            {
                moveLeft(wheel, 3);
                if (flag[2== 1)
                {
                    moveRight(wheel, 2);
                    if (flag[1== 1)
                    {
                        moveLeft(wheel, 1);
                        if (flag[0== 1)
                        {
                            moveRight(wheel, 0);
                        }
                    }
                }
            }
            else if (dir == 1)
            {
                moveRight(wheel, 3);
                if (flag[2== 1)
                {
                    moveLeft(wheel, 2);
                    if (flag[1== 1)
                    {
                        moveRight(wheel, 1);
                        if (flag[0== 1)
                        {
                            moveLeft(wheel, 0);
                        }
                    }
                }
            }
        }
 
    }
    ret = 0;
    if (wheel[0][0== 1)ret += 1;
    if (wheel[1][0== 1)ret += 2;
    if (wheel[2][0== 1)ret += 4;
    if (wheel[3][0== 1)ret += 8;
 
    cout << ret << '\n';
}
cs


반응형

'PS > 백준' 카테고리의 다른 글

2448번 별 찍기 - 11  (0) 2018.11.12
1966번 프린터 큐  (0) 2018.10.28
7576번 토마토  (0) 2018.10.24
2839 설탕배달  (0) 2018.10.19
15686번 치킨 배달  (0) 2018.10.14

문제 링크 : https://www.acmicpc.net/problem/15686


해결 방법)


풀고나서 다른 해결방법들을 보니까 대게 비슷하게 푼것같다. 

그래도 내가 푼 아이디어를 풀어보고자 한다. (누군가에게는 도움이 되겟지하는 생각에)

치킨집 고르는 경우 즉 M개(1개의 치킨집, 2개의 치킨집, 3개의 치킨집 ...... M개의 치킨집) 에서 모든 집들과의 거리중 최소거리만 구하여 이 최소거리의 합들이 우리가 구하고자하는 도시의 치킨거리값이 되는 것이다.


그런데 우리는 1개를 어떻게고르고 2개를 어떻게고르고에 대한 아이디어가 없당 ㅜ 이것은 재귀적으로 상황을 두개 만들어 주면 된다. 있고, 없고의 두가지상황인데 A,B,C의 치킨집이있다고하면,

A 있고 B 있고, C 없고

A 없고 B 있고 C 없고 .... 요론식으로 하다보면 모든 경우의수를 찾을 수 있다는 느낌을 받을 수 있다.

즉 각 치킨집마다 있고 없고의 상황 두가지를 만들어서 치킨집을 먼저 고를 수 있다.


이제 골라진 치킨집이 1개일때,2개일때 ,3개일때, 4개일때..... M개 이하 일때 마다 치킨 거리 총합을 알아야지 도시의 치킨거리를 알 수 가있는데 어떻게 골라진 치킨집 개수마다 그 치킨거리 총합을 알아낼 것인가가 문제이다.


이 해결방법은 모든 집마다 거리를 구하는데 골라진 집들과의 사이를 구하면서 최소값을 각 집마다 구해나가는 것이다.

우리는 각치킨집마다 경우를 있고,없고의 두가지 경우를 만들었는데, 이때 치킨집이 있다라면 이 치킨집은 골라진녀석이고 따로 골라졌다라는 표식을 남겨두면 나중에 골라진 치킨집에대해 거리값을 구해나갈수 있다.

따라서 골라진 치킨집과 모든 집들사이의 거리를 구할 수 있게되고 당연히 최소값도 구하게되면서 이 최소값들의 총합이 결국엔 우리가 구하는 답이 된다.


또 참고로 최대 M개라고해서 M개를 골랐을때만 왜 조건을 거냐라고 말할 수 있는데, 어차피 FOR문을 돌면 각집이 치킨집들 중 최소값만 지니기 때문에 하나의 치킨집만 선택된경우도 자연스레 포함이 되어 모든 경우를 내포하기때문이다.


소스코드)


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
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int ans = 987654321// 도시의 치킨거리
int M;
int visit[13];
vector<pair<intint>> home; // 집좌표
vector<pair<intint>> chicken; // 치킨 좌표
int csize;
int min(int a, int b) { return a < b ? a : b; }
void solve(int inow, int cnt_now)
{
    if (cnt_now == M) // 최대 M개를 고를때
    {
        int d; // 두점사이의 거리
        int x1, x2;
        int y1, y2;
        int tmp = 0;
        int homesize = home.size();
        for (int i = 0; i < homesize; i++)
        {
            int minnum = 987654321;
            for (int j = 0; j < csize; j++)
            {
                if (visit[j]) 
                {
                    d = abs(home[i].first - chicken[j].first) + abs(home[i].second - chicken[j].second);
                    if (minnum > d)
                        minnum = d;
                }
            }
            tmp += minnum;
            
        }
        ans = min(ans, tmp); //도시치킨거리 갱신
        return;
    }
    if (inow >= csize) return
    visit[inow] = 1;// 현재 치킨집 선택
    solve(inow + 1, cnt_now + 1); 
    visit[inow] = 0
    solve(inow + 1, cnt_now);
}
int main()
{
    int N;
    int num;
    cin >> N >> M;
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            scanf("%d"&num);
            if (num == 1)
            {
                home.push_back({ i,j });
            }
            else if (num == 2)
            {
                chicken.push_back({ i,j });
            }
        }
    }
    csize = chicken.size();
    solve(00);
    printf("%d\n",ans);
}
cs


반응형

'PS > 백준' 카테고리의 다른 글

2448번 별 찍기 - 11  (0) 2018.11.12
1966번 프린터 큐  (0) 2018.10.28
7576번 토마토  (0) 2018.10.24
2839 설탕배달  (0) 2018.10.19
14891번 톱니바퀴  (0) 2018.10.15

문제링크 : https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5LrsUaDxcDFAXc&categoryId=AV5LrsUaDxcDFAXc&categoryType=CODE

(로그인 해야볼수있듬!)


해결 방법 :


쉬운난이도 문제라고해서 풀어보았는데, 하도 안풀려서 다른 사람의 힌트를 얻고 겨우 풀어낸 문제....


이 문제의 핵심은 최대이득을 구하기위해서는 사고팔고를 적절히 해야하는 방법을 생각해야하는데


그 방법이 맨뒤에서 부터 처음까지 도는 가운데 최대가격의 값을 기준으로 이득이 생기는 부분의 총합을 더하는 것이었다.


내가 헤맨것이 모든 가격을 내림차순으로 최대값순으로 새로운 배열을 만들고 만든 배열과 주어진 가격 배열을 하나씩 비교해 나가면서 더해나간게 문제였다.

예시의 테스트케이스는 다 통과되서 아 이게 맞다라고 생각하고(답정) 한게 큰 패인이다..

1 1 4 5 2 1 이 테스트케이스만 보더라도  5 4 2 1 1 1 이런 새로운 배열과 하나씩 비교할텐데, 4가 5안에 포함되어버려 이미 계산이 끝낫지만 여전히 새로운 배열에 비교 대상으로 존재해있어서  뒤에 2, 1 부분도 계산을 해준것이기 때문이다 ... 


엄청난 뻘짓을 하고나서 힌트를 본후 , 대부분 사람들은 뒤에서 부터 계산을 해서 답을 찾았다는 것을 보았고, 

아 그럼 뒤에서 부터 최대값을 갱신해주고 그 최대값보다 작으면 계속더해가는 방식이 모든 경우를 해결해 줄 수 있다는 것을 알게되었다.


위의 1 1 4 5 2 1 을 보면

맨뒤의 1을 max로 둔다.

그리고 맨뒤에서부터 처음일때까지 전부 비교해준다.

만약 현재 max 보다 크다면 max만 갱신해준다.

아니라면 max값보다 작으므로 이득을 더해나가준다.

이렇게 전부 계산해주고나면, 이득생기는 부분을 전부더해줘서 최대이득을 구할 수 있게된다.


소스코드) 


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<iostream>
long long max_margin = 0;
int cost[1000001];
using namespace std;
int main()
{
    int test_case;
    
    cin >> test_case;
    for (int t = 1; t <= test_case; t++)
    {
        max_margin = 0;
        int max_price;
        int n;
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            scanf("%d"&cost[i]);
        }
        max_price = cost[n - 1];
        for (int i = n - 2; i >= 0; i--)
        {
            if (max_price > cost[i])
            {
                max_margin += max_price - cost[i];
            }
            else
            {
                max_price = cost[i];
            }
        }
        printf("#%d %lld\n", t, max_margin);
    }
}
cs


반응형

'PS > SWEA' 카테고리의 다른 글

5986번 새샘이와 세 소수  (0) 2018.11.03
2007번 패턴 마디의 길이  (0) 2018.10.16
5550번 나는 개구리로소이다  (0) 2018.10.06
1926번 간단한 369게임  (0) 2018.10.05
1868번 파핑파핑 지뢰찾기  (0) 2018.09.30

문제링크  : https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWWxqfhKAWgDFAW4&categoryId=AWWxqfhKAWgDFAW4&categoryType=CODE&&&

(로그인 해야볼수있듬!)


해결방법 )

하나의 개구리는 한번의 울음소리 뿐만아니라 여러번 운다는 것이 문제의 힌트같다.

내가 선택한 방법은 전체울음소리와 check할 "croak"을 순차적으로 검사를 하고 원래 녹음된 울음소리에서 기본울음소리 패턴을 제거해 주는 방식을 하면서 답을 구했다. 한번 루프를 돌때마다 cnt를 증가해서 개구리 수를 구했다. (일단 연속되게 운 개구리 한마리를 먼저 걸러내주기 위해서!)



ex)  


1)

기본울음소리위치 값과 녹음된 울음소리의 위치 값이 똑같다면 녹음된 울음소리에서 그 값을 빼준다.

그리고 pos 위치를 다음 검사 위치로 이동함!


2)


여기서 눈여겨 봐야할 곳은 녹음된 울음소리의 위치이다.

녹음된 울음소리는 Vector에 저장시키기 때문에 erase(a+i) 를 써서 i번째위치를 삭제시키고 그래서 자동으로 앞으로 당겨지게되어 size가 하나 줄어든다.

그리고 pos 현재위치값과 녹음된 울음소리 위치값이 다르기 때문에 반복인덱스를 하나 증가시킨다.


3)




기본울음소리위치 값과 녹음된 울음소리의 위치값이 똑같기 때문에 제거해주고 뒤에도 남은 위치값이 같으므로 전부 빼지게 된다.

이렇게 되면 녹음된 울음소리에는 “C”만 남게된다.

검사위치가 4까지가서 전부 탐색이 된것이고 5가되면 0으로 다시 만들어줘서 CROAK을 전부 제거했다라는 의미를 부여함 

  -> pos 위취가 0이면 재탐색 가능!


4)



CPos 처음 값과 같기 때문에 빼준다.

최종적으로 녹음된 울음소리는 없기 때문에 전부 검사를 하게 된 것! 이고, 밑에 기본울음소리에서 검사위치가 0이 아니기때문에 완전한 CROAK을 못만들었다는 의미라서 -1 출력한다. 만약 0이면 CROAK을 전부 제거했다라는 의미라서 다음 루프타는 것이 가능함



[예외의 경우]


처음부터 검사위치 값과 맞지 않아서, 예외의 경우가 발생하는데

(우리는 한루프를 돌고나서 POS위치가 0이면 CROAK을 전부제거됬다고 정의했기때문) 이는 flag 변수를 설정해서 한번이라도 같은 것이 없는것도 -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
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<iostream>
#include<vector>
#include<string>
using namespace std;
char check[6= "croak"
vector <char> v; 
int main()
{
    int test_case;
    cin >> test_case;
    for(int t= 1; t<=test_case; t++)
    {
        bool flag = false;
        bool visit = false;
        int cnt = 0;
        int vsize = 0;
        int k = 0;
        int pos = 0;
        string str;
        cin >> str;
        int len = str.length();
        for (int i = 0; i < len; i++)
        {
            v.push_back(str[i]);
        }
     
        while (!v.empty())
        {
            vsize = v.size();
            k = 0// 만약 check와 같은 문자가 있으면 k 값으로 사이즈를 줄여주기위해서 필요함
            pos = 0;
            flag = false;
            visit = false;
            for (int i = 0; i < vsize - k; i++)
            {
                if (v[i] == check[pos])
                {
                    v.erase(v.begin() + i);
                    k++//size 하나 줄임
                    i--// i제자리 만들기위해 하나 빼줌
                    pos++// pos는 다음 뺄것을 준비하기위해 그위치로 이동
                    if (pos == 5)
                    {
                        pos = 0;// 다뺏으면 0으로 돌린후 다음 울음소리를 빼기위해 쎗팅!
                    }
                    visit = true// 이 문자는 있다.
                }
            }
            //한루프가 끝나면 pos 위치 확인
            if (pos != 0 || visit == false)
            {
                flag = true
                break;
            }
            cnt++
        }
        if (flag)
        {
            printf("#%d -1\n", t);
            v.clear();
        }
        else
            printf("#%d %d\n", t, cnt);
        }
    
}
cs


반응형

'PS > SWEA' 카테고리의 다른 글

2007번 패턴 마디의 길이  (0) 2018.10.16
1859번 백만 장자 프로젝트  (0) 2018.10.13
1926번 간단한 369게임  (0) 2018.10.05
1868번 파핑파핑 지뢰찾기  (0) 2018.09.30
SWEA - 혜리의 숫자 나누기  (0) 2018.09.23

 1 2 3 4 5 6 7 8 9



입력10


출력1 2 - 4 5 - 7 8 - 10


3, 6, 9 가 들어가있으면 박수대신 "-" 표시를 출력한다. 이때, 333 이라는 숫자가 들어오면 --- 으로 출력된다.


해결방법)


n이 입력되면

1부터 n까지 주어지는 상황에서

각 숫자 자리마다 3,6,9가 있는지 확인한 후 있으면 있는만큼 "-"출력한다. 없으면 원래 숫자를 출력한다.


여기서 각 숫자마다 자리를 나눠서 확인을 해줘야하는데 10으로 계속 나눠주면서 몫이 0일때 까지 반복한다.

그래서 반복마다 생겨나는 나머지가 각 자리수이기 때문에 이 자리수가 3,6,9인지를 확인해 주었다.

예시) 245 / 10 = 24,  245 % 10 = 5(일의자리수 추출)  -> 24/10 = 2, 24%10 = 4(십의자리수 추출) -> 2/10= 0, 2%10 = 2(백의자리수 추출)


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<iostream>
using namespace std;
int main()
{
    int n;
    int num;
    int mok;
    int obj; // 나누는 대상
    int r; // 나머지값
    bool flag = 0//1로 켜지면 3,6,9가 하나라도 있었다라는것 
    cin >> n;
    for(int num = 1; num<=n; num++)
    {
        obj = num;
        flag = 0;
        do
        {
            r = obj % 10;
            if(r == 3 || r == 6 || r == 9)
            {
                flag = 1;
                printf("-");
            }
            mok = obj/10;
            obj = mok;
        }while(mok!=0);
        if(flag == 1)
        {
            printf(" ");
            continue;
        }
        printf("%d ",num);
    }
}
cs


반응형

'PS > SWEA' 카테고리의 다른 글

2007번 패턴 마디의 길이  (0) 2018.10.16
1859번 백만 장자 프로젝트  (0) 2018.10.13
5550번 나는 개구리로소이다  (0) 2018.10.06
1868번 파핑파핑 지뢰찾기  (0) 2018.09.30
SWEA - 혜리의 숫자 나누기  (0) 2018.09.23

풀이방법)

나는 먼저 0인 좌표(주변의 지뢰가 없는곳)를 찾아 탐색을 해서 먼저 방문영역을 체크해두기로했다.

 - 여기서 탐색을 한다는 것은 한번의클릭으로 모두 제거되는 것이기 때문에 카운트를 하나로 취급해준다.

그리고 모든 좌표를 탐색하면서 방문이 안된 녀석들은 주변에 지뢰가 있는 것이기때문에 하나씩 카운트를 세준다.


1. 모든좌표마다 8방향 주변에 지뢰개수를 파악해서 그 개수를 표시해주는 맵을 새로 만든다.


2. 새로운 맵에서 0인 좌표부터 bfs 탐색을 시작해서 주변의 영역을 방문표시해둔다. 


3. 인접한 0들은 모두 2번에서 없어진 것이고, 나머지 방문안된 0도 bfs탐색을 하면서 주변영역을 방문표시해준다.


4. bfs탐색을 한번할때마다 카운트를 1씩증가한다.


5. 최종적으로 원래 맵을 돌면서 방문안된 좌표는 하나씩 카운트를 세주고 3번에서 구한 카운트와 합산하면 정답이다.


 

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int changemap[301][301= { 1, };
char basemap[301][301];
int visit[301][301];
int n;
int dx[] = { -1,-1,-1,0,1,1,1,0 };
int dy[] = { -1011,1,0,-1,-1 };
queue< pair<intint> > q;
bool isInmap(int x, int y)
{
    if (x <0 || x >- 1 || y<0 || y>- 1)
    {
        return false;
    }
    else
        return true;
}
void Change()
{
 
    for (int x = 0; x<n; x++)
    {
        for (int y = 0; y<n; y++)
        {
            //각 좌표마다 8방향에서 지뢰개수를 채워나간다.
            int cnt = 0;
            if (basemap[x][y] == '*')
            {
                changemap[x][y] = -1;
                continue;
            }
            for (int i = 0; i<8; i++)
            {
                int tx = x + dx[i];
                int ty = y + dy[i];
                if (basemap[tx][ty] == '*')
                {
                    cnt++;
                }
            }
            changemap[x][y] = cnt;
 
        }
    }
}
void bfs(int x, int y)
{
    // bfs탐색으로 0인 좌표에서 8방향 값을 visit 체크해준다. 
    int nx, ny, nnx, nny;
    q.push({ x,y });
    while (!q.empty())
    {
        nx = q.front().first;
        ny = q.front().second;
        visit[nx][ny] = 1;
        for (int i = 0; i<8; i++)
        {
            nnx = nx + dx[i];
            nny = ny + dy[i];
            if (!isInmap(nnx, nny))
            {
                continue;
            }
            if (!visit[nnx][nny])
            {
                visit[nnx][nny] = 1// 방문안된 좌표는 방문처리해준다. 중복 방문표시 예방 
                if (changemap[nnx][nny] == 0)
                {
                    q.push({ nnx,nny });
                }
            }
        }
        q.pop();
    }
}
int main()
{
    int T;
    scanf("%d"&T);
    for (int t = 1; t <= T; t++)
    {
        int ret = 0;
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                scanf(" %c"&basemap[i][j]);
            }
        }
        Change();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (changemap[i][j] == 0 && !visit[i][j])
                {
                    bfs(i, j);
                    ret++// bfs탐색한다면 클릭횟수증가. 
                }
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (changemap[i][j] > 0 && !visit[i][j])
                {
                    ret++;
                }
            }
        }
        printf("#%d %d\n", t, ret);
        memset(visit, 0sizeof(visit));
    }
}
cs


반응형

'PS > SWEA' 카테고리의 다른 글

2007번 패턴 마디의 길이  (0) 2018.10.16
1859번 백만 장자 프로젝트  (0) 2018.10.13
5550번 나는 개구리로소이다  (0) 2018.10.06
1926번 간단한 369게임  (0) 2018.10.05
SWEA - 혜리의 숫자 나누기  (0) 2018.09.23

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/42578#
문제 설명

스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.

예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.

종류이름
얼굴동그란 안경, 검정 선글라스
상의파란색 티셔츠
하의청바지
겉옷긴 코트

스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

제한사항
  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
  • 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
  • 같은 이름을 가진 의상은 존재하지 않습니다.
  • clothes의 모든 원소는 문자열로 이루어져 있습니다.
  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.
  • 스파이는 하루에 최소 한 개의 의상은 입습니다.
입출력 예

clothesreturn
[[yellow_hatheadgear], [blue_sunglasseseyewear], [green_turbanheadgear]]5
[[crow_maskface], [blue_sunglassesface], [smoky_makeupface]]3


해결 방법)


한 4번정도 시도끝에 도저히 아이디어가 안떠올라서 힌트를 얻으러 돌아다녔다 


마침 이문제를 푼 사람을 발견했고, 그사람이 푼 과정을 보게 되었다. (감사합니당 알려주셔서 ㅎㅎ)

그런데 내가 멍청한건지 그 과정을 봐도 이해를한번에 하기 힘들었다.


그래도 푼 사람이니까 믿고 그 방법순서대로 그려가면서 이해해보려했다.

어 그러니까 이게 무슨일이지 그 방법대로하니까 모든 조합의 수가 나와버렸다 ....... 


그 방법은 예를 들어서 설명해보겠다.


example) 

배가 a, b, c 라는 이름의 3개가 있다.

귤은 e, f 라는 이름의 2개가 있다.


여기서 배는 안골랐다라는 경우를 포함해서 (0,a,b,c) 4개가 된다. 

마찬가지로 귤도 안골랐다라는 경우를 포함해서 (0,e,f) 3개가 된다.

이렇게 되면 4*3 =  12가지이고 여기서 0,0 인 둘다 안고르는 경우는 없기 떄문에 -1을 해주면 11가지로 답을 구할 수 있다.


종류를 하나 더 추가해서 보면


배 a,b,c 3개 

귤 e,f 2개

사과 g, h ,i 3개

이렇게 주어졌다고하고 위의 방법대로 하면,

(배 + 1) * (귤 + 1) * (사과 +1) -1 이 총 가지수가 된다.


저기 + 1은 그 종류를 안고른 경우가 되기때문에 모든 조합의 가지수가 나오게된다.


알고리즘 구성을 보면

입력받은 2차원 문자열 배열에서 같은 종류마다 있는 개수 정보를 저장한다.

그리고 그 개수마다 +1 씩해가며 모든 종류를 곱해준다. 

최종적으로 구해진 값에 -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
28
29
30
31
32
33
34
35
36
37
38
#include <string>
#include <vector>
int a[31= { 0, };
int v[31];
using namespace std;
 
int solution(vector<vector<string>> clothes) {
    int answer = 0;
    int size ;
    int ret = 1;
    size = clothes.size();
    for(int i =0 ;i<31; i++)
    {
        v[i] = 0;
    }
    for(int i = 0; i<size; i++)
    {
         if(v[i] == 1)
                continue;    
         for(int j = i ; j<size; j++)
         {
            if(clothes[i][1== clothes[j][1] )
            {
                a[i]++// i번째 종류 증가
                v[j]= 1;
            }
        }
    }
    for(int i = 0 ; i< 31; i++)
    {
        if(a[i]>0)
        {
            ret *= (a[i] +1);
        }
    }
    answer = ret - 1;
    return answer;
}
cs




반응형

캔디팡 문제 링크 : http://codeup.kr/JudgeOnline/problem.php?id=2605


해결 전략)


2차원 맵정보가 있는데 각 좌표마다 방문하면서 4방향(상,하,좌,우)에 인접해있는 모든 개수정보를 알고 결국, 인접해있는개수가 3개이상이면 카운팅을 해줘서 답을 구할수있다.

문제예시그림예를 들어서 그린 그림입니다.


여기서 인접해 있는 것이 보인다면 그 곳으로 좌표이동하고 다시 4방향으로 인접해 있는 개수정보를 파악한다.


이 작업을 모든 맵 좌표를 방문하면서 체크하게 된다. 단, 방문이 된 곳은 체크를 따로해줘서 재탐색이 이뤄지지 않도록 한다.


소스코드)

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
#include<stdio.h>
int map[8][8];
int visit[8][8];
int ret;
int cnt_ret;
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,-1,1 };
int solve(int r, int l)
{
    // 4방향에서 현재숫자와 같은것을 비교하여 캔디팡이 터지는 영역을 카운팅 하는함수
    int tx, ty;
    int cnt =1 ;
    visit[r][l] = 1;
    for (int i = 0; i < 4; i++)
    {
        tx = r + dx[i];
        ty = l + dy[i];
        if (tx < 1 || tx > 7 || ty < 1 || ty >7)
        {
            continue;
        }
        else
        {
            if (!visit[tx][ty] && (map[tx][ty] == map[r][l]))
            {
                cnt += solve(tx, ty);
            }
        }
    }
    return cnt;
}
int main()
{
    for (int i = 1; i <= 7; i++)
    {
        for (int j = 1; j <= 7; j++)
        {
            scanf("%d"&map[i][j]);
        }
    }
    for (int i = 1; i <= 7; i++)
    {
        for (int j = 1; j <= 7; j++)
        {
            ret = solve(i,j);
            if (ret >= 3)
            {
                cnt_ret++;
            }
        }
    }
     
    printf("%d\n", cnt_ret);
}
 
cs


반응형

'PS > 코드업' 카테고리의 다른 글

3704번 계단 오르기 2  (0) 2019.03.31
1920번 2진수 변환 (재귀함수)  (0) 2019.03.16
3733번 우박수 길이 - large  (0) 2019.01.27
2606. 소수점 이하 출력  (0) 2018.12.17
재귀함수 1부터 n까지 합 구하기  (0) 2018.11.18

처음에 완전 탐색을 하면서 막대기가 생겨나는 경우의 수(있고 없고)마다 생겨나는 숫자를 M으로 나눠 지는지를 확인했다.

하지만 계속 틀리면서 다시 문제를보니 30만 자리라는 어마어마한 숫자 크기때문에 이렇게 풀면은 안되는 구나를 느꼇다. 

결국 질문을 해서 힌트를 얻은결과 숫자 나누는 방법을 적용해서 풀면은 해결할 수 있다고 생각했다.

(나누기는 초딩때부터 아는건데...... 아주 세세하게 들어가서 나머지가 구해지는 과정을 그려보니 알 수 있었다.)



막대기 마다 생겨나는 부분이 M배수가 되는지 확인하면서(%M == 0) 막대기를 배치 시킬 수 있는 경우의 수를 구한다.

혜리 숫자 나누기 설명

위에서 보면 막대기가 가능한 부분은 파란 부분인데, 여기서 생겨나는 왼쪽부분과 오른쪽부분이 M으로 나눠지는지 확인하면서 나눠지면 막대기가 존재할수 있는 수를 카운팅 해준다.


모든 개수를 세주고나서 최종적으로 구한 경우의 수에 -1을 해주면서 CASE 6의 막대기 생겨나는 경우의 수를 없애준다. 왜냐하면 이미 CASE1~5까지 CASE6에 해당하는 부분을 포함하기때문에 -1을 해주는 것이다. 즉, 2^구한 막대기 경우의수-1 을 하면 정답이 되게된다.


막대기때문에 생겨나는 숫자가 M으로 나눠지는지 확인하는 방법은 다음과 같다.

EX) 123456이 7로 나눠지는지 확인 하는 과정 - 우리는 보라색 부분의 식을 반복하면서 최종적으로 0인지 확인하면 된다.


소스코드)

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<cstdio>
#include<iostream>
using namespace std;
int a[300000];//30만개 숫자
int N;
int M;
 
void solve(int t)
{
    int before = 0;
    int mod = 0;
    int ret = 1;
    int cnt = 0;
    bool flag = false;
    for (int i = 0; i < N; i++)
    {
        mod = (10 * before) + a[i]; // 다음 숫자 생성
        mod = mod % M; //숫자를 나눠본다.
        if (mod == 0// 나눠지면 막대기 개수 증가
        {
            cnt++;
            if (i == N - 1)
                flag = true;
        }
        before = mod; // 숫자 생성위해서 현재 나눈 나머지 값을 before로 넘겨준다.
    }
    if (!flag)
    {
        printf("#%d 0\n", t);
        return;
    }
    else
    {
        cnt--;
        for (int i = 0; i < cnt; i++)
        {
            ret = (ret * 2) % 1000000007;
        }
        printf("#%d %d\n", t, ret);
    }
}
int main()
{
    int T;
    scanf("%d\n"&T);
    for (int i = 1; i <= T; i++)
    {
        scanf("%d %d"&N, &M);
        for (int i = 0; i < N; i++)
        {
            scanf("%1d"&a[i]);
        }
        solve(i); 
    }
    return 0;
}
cs


반응형

'PS > SWEA' 카테고리의 다른 글

2007번 패턴 마디의 길이  (0) 2018.10.16
1859번 백만 장자 프로젝트  (0) 2018.10.13
5550번 나는 개구리로소이다  (0) 2018.10.06
1926번 간단한 369게임  (0) 2018.10.05
1868번 파핑파핑 지뢰찾기  (0) 2018.09.30

+ Recent posts