전체 글 (162)
2024-03-25 23:14:22

뭐 말을 좀 꼬아 놨는데, 쉽게말해 첫째 줄에 N, M이 주어진다.

2번째 줄 부터 N+1 줄 까지는 첫번째 배열에 들어가는 문자열들이 주어지고,

N+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
35
36
37
38
39
40
41
42
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            int[] input = Array.ConvertAll(reader.ReadLine().Split(), int.Parse);
            int N = input[0]; int M = input[1];
 
            string[] str1 = new string[N];
            string[] str2 = new string[M];
 
            for (int i = 0; i < N; i++)
                str1[i] = reader.ReadLine().ToLower();
            HashSet<string> set1 = new HashSet<string>(str1);
 
            for (int j = 0; j < M; j++)
                str2[j] = reader.ReadLine().ToLower();
            Array.Sort(str2);
 
            int cnt = 0;
            
            foreach (string s in str2)
            {
                if (set1.Contains(s))
                    cnt++;
            }
 
            print.WriteLine(cnt);
 
        }
    }
}
cs

각 배열에 문자열들을 N회, M회 만큼 입력받아서 넣어준다.

비교군이 들어있는 1번 배열은 해시셋으로 만들어준다.

비교를 할 두번째 배열은 정렬을 해 둔다. (해시셋을 통한 인덱싱은 정렬이 필수)

그리고 배열 1이 배열 2의 내용을 포함하는지 검사 해준 후, 있으면 카운트를 1 증가, 없으면 통과 하여 ㅗ최종적으로 카운트 값을 출력해주면 된다.

 

'하루 한 접시' 카테고리의 다른 글

[백준] 좌표 압축 [C#]  (0) 2024.03.25
[백준] 1037 약수 [C#]  (0) 2024.03.25
[백준] 2839번: 설탕 배달 [C#]  (1) 2024.03.24
[백준] 1018 체스판 다시 칠하기 [C#]  (0) 2024.03.24
[백준] 1764번: 듣보잡 [C#]  (1) 2024.03.24
2024-03-25 00:06:25

악마의 수는 666이 들어있는 숫자를 말한다고 한다.

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
39
40
41
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            int N = int.Parse(reader.ReadLine());
 
            string num = "666";
            int count = 0;
 
            while(count != N)
            {
                for(int i = 0; i+2 < num.Length; i++)
                {
 
                    if (num[i] == '6' && num[i + 1== '6' && num[i + 2== '6')
                    {
                        count++;
                        if (count == N)
                            sb.Append(num);
                        break;
                    }
                }
                num = (int.Parse(num) + 1).ToString();
            }
 
            print.WriteLine(sb);
            
        }
    }
}
cs

 

우선, 몇 번째 악마의 수를 찾을 것인지 입력받는다.

이후 루프를 돌며 이번 숫자의 n번째, n+1번째, n+2 번째가 6인지 체크한다.

만약 6이 3번 연속되어 나타난다면, 카운트를 하나 올려서 몇 번째 악마의 수를 찾은 것인지 저장한다.

이후 N과 카운트 횟수가 같다면 해당 악마의 수를 출력하고, 루프를 종료한다.

while문의 경우 카운트 횟수가 N보다 클 경우 종료되기 때문에 따로 break문을 쓰지 않아도 된다.

2024-03-24 23:20:15

상근이가 배달해야 할 설탕의 무게가 주어진다.

상근이는 설탕을 3킬로 혹은 5킬로밖에 운반할 수 없다.

이때 상근이가 설탕을 배달할 수 있는 최소 운반 횟수를 출력하고, 배달이 불가능하다면 -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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int sugar = int.Parse(Console.ReadLine());
            int weight = 3;
            int temp = 0;
 
            int tot_cnt = 1;
            bool found = false;
 
            while(weight <= sugar && !found)
            {
                temp = weight;
                for(int count = 0; count <= tot_cnt; count++)
                {                    
                    if (weight == sugar)
                    {
                        Console.WriteLine(tot_cnt);
                        found = true;
                        break;
                    }
                    weight += 2;
                }
                weight = temp+3;
                tot_cnt++;
 
            }
            if(!found)
                Console.WriteLine("-1");
 
        }
    }
}
 

 

처음에 문제를 보고 어떻게 알고리즘을 짜야 할 지 고민했다.

하지만 고민은 사치였다. 왜냐면 이건 부르트포스 문제니까.

그냥 모든 경우의 수를 따져보면 되는 일이다.

그래도 수의 증가하는 경향을 따져보기 위해 대충 그림을 그려보았다.

그림을 그려보니 루프가 1회 반복될 때 마다 가장 낮은 무게가 전 루프의 가장 낮은 무게보다 3 증가하였다.

그리고 운반 가능한 무게는 2씩 증가하는 모습을 보여주었다.

그래서 가장 낮은 무게를 기억해두고, 루프를 돌며 2씩 더해주었다.

루프 종료 후 저장해둔 무게를 불러와 3을 증가시킨 후, 반복할 횟수를 1회 늘려주며 다음 루프를 준비해 주었다.

이렇게 루프를 돌며 입력받은 설탕의 무게와 루프 중 가능한 설탕의 무게가 일치한다면 해당 무게를 출력해 주고

루프를 완전히 빠져나와주었다. 하지만, 입력받은 설탕의 무게보다 루프 가능한 무게 중 가장 낮은 무게의 값이 더 크다면 루프를 종료하고 -1을 출력해 주었다.

2024-03-24 21:51:10

첫줄에 Y축과 X축의 길이가 한줄로 주어진다.

이후 고쳐야 할 체스판이 주어진다.

고쳐야 할 수가 제일 적은 체스판의 고칠 칸의 숫자를 출력해주면 된다.

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static char[,] board;
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
 
            int[] lines = Array.ConvertAll(reader.ReadLine().Split(), int.Parse);
            int x = lines[1];
            int y = lines[0];
 
            board = new char[y, x];
 
            for (int i = 0; i < y; i++)
            {
                string line = reader.ReadLine();
                for (int j = 0; j < x; j++)
                {
                    board[i, j] = line[j];
                }
            }
 
            int cnt = int.MaxValue;
 
            for (int a = 0; a+7 < y; a++)
            {
                for (int b = 0; b+7 < x; b++)
                {
                    cnt = Math.Min(cnt, checkBoard(a, b));
                }
            }
 
            print.WriteLine(cnt);
 
        }
 
        static int checkBoard(int x, int y)
        {
            int top_is_white = 0;
            int top_is_Black = 0;
 
            for(int i = 0; i < 8; i++)
            {
                for(int j = 0; j < 8; j++)
                {
                    if((i + j) % 2 == 0 )
                    {
                        if (board[x+i, y+j] == 'W')
                            top_is_Black++;
                        if (board[x+i, y+j] == 'B')
                            top_is_white++;
                    }
                    else
                    {
                        if (board[x+i, y+j] == 'W')
                            top_is_white++;
                        if (board[x+i, y+j] == 'B')
                            top_is_Black++;
                    }
                }
            }
 
            return Math.Min(top_is_Black, top_is_white);
 
        }
 
    }
}
cs

 

가독성을 위해 checkBoard 함수를 따로 빼두었기 때문에, 체스판을 담을 배열을 static으로 전역화 해주었다.

이후 좌표의 크기가 Y축, X축으로 주어졌는데, 이는 이차원 배열이 [y축, x축] 으로 되어있기 때문이다.

사람의 관점에서 당연히 x, y로 읽다 보니 자주 에러가 났었다.

부르트 포스 문제인 만큼 알고리즘 따위 생각하지 않고 무식하게 모든 경우의 수를 체크해주면 해결 할 수 있다.

알고리즘을 짜는것 보다 좌표가 너무 헷갈려서 힘들었다.

 

2024-03-24 00:19:06

첫째 줄에 두 배열의 입력 횟수가 한 줄로 주어진다. (N, M)

두번째 줄부터 N번째 줄 까지 듣지 못한 사람들이 입력된다.

N+1 번째 줄부터 M번째 줄 까지 보지 못한 사람들이 입력된다.

모든 입력은 소문자로 주어지고, 각 배열에는 중복 입력이 허용되지 않는다.

두 배열에 모두 속하는 사람을 찾아 "사전순"으로 출력해준다

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            int[] num = Array.ConvertAll(reader.ReadLine().Split(), int.Parse);
            int NS = num[0]; int NH = num[1];
 
            string[] neverSeen = new string[NS];
            string[] neverHeard = new string[NH];
 
            for (int i = 0; i < NS; i++)
            {
                neverSeen[i] = reader.ReadLine();
            }
 
            for (int j = 0; j < NH; j++)
            {
                neverHeard[j] = reader.ReadLine();
            } Array.Sort(neverHeard);
 
            HashSet<string> set1 = new HashSet<string>(neverSeen);
 
            int count = 0;
            foreach (string a in neverHeard)
            {
                if (set1.Contains(a))
                {
                    sb.Append(a + "\n");
                    count++;
                }
            }
 
            print.WriteLine($"{count}\n" + sb);
        }
    }
}
cs

지금까지는 string배열에 입력을 받아서 쪼개놓기만 한 후,  int형 배열에 넣어주는 방법을 사용했는데,

이제는 입력을 받은 즉시 int형으로 형변환 해서 int형 배열에 저장할 수 있게 되었다.

그리고 두 배열의 내용물을 비교할 때

전수조사 (시간 복잡도 O(n^2)) 혹은 이진 탐색 (시간 복잡도 O(log n)) 을 사용했었는데, 시간 초과가 뜨는 걸 보고 더 좋은 방법이 없을까 싶어서 찾아봤는데, HashSet 을 이용한 방법이 있었다.

이 방식을 사용하면 해시셋에 데이터를 입력하는 시간 O(n)과 데이터를 찾는데 O(1)의 시간만이 걸리기 때문에 시간을 아주 많이 줄일 수 있게 되었다.

 

2024-03-23 01:34:59

첫째 줄에는 입력될 정수들의 개수가, 둘째 줄에는 정수들이 문자열 형식으로 한 줄로 입력된다.

셋째 줄에는 찾을 정수들의 개수가, 넷째 줄에는 찾을 정수들이 한 줄로 입력된다.

넷째 줄에 입력된 정수의 개수를 한 줄로 출력하면 되는 문제이다.

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            int N = int.Parse(reader.ReadLine());
 
            int[] num = new int[20_000_001];
 
            string[] str1 = reader.ReadLine().Split();
 
            for (int i = 0; i < N; i++)
            {
                num[int.Parse(str1[i])+10_000_000]++;
            }
 
            int M = int.Parse(reader.ReadLine());
 
            string[] str2 = reader.ReadLine().Split();
 
            for (int a = 0; a < M; a++)
            {
                int low = -10_000_000; int high = num.Length - 1;
                bool found = false;
                while(high >= low && !found)
                {
                    int mid = (low + high) / 2;
                    if (mid == int.Parse(str2[a]))
                    {
                        found = true;
                        sb.Append(num[mid+10_000_000] + " ");
                        break;
                    }
                    else if (mid > int.Parse(str2[a]))
                        high = mid - 1;
                    else
                        low = mid + 1;
                }
                if (!found)
                    sb.Append("0 ");
            }
 
            print.WriteLine(sb);
        }
    }
}
cs

지금까지 항상 양수로 주어졌던 정수가 이제는 음수로도 주어진다.

그렇기 때문에, 인덱스 번호의 값을 증가시킬 때, 해당 인덱스 번호에 10_000_000을 더해서 증가시켜야 한다.

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            int N = int.Parse(reader.ReadLine());
 
            int[] num = new int[20_000_001];
 
            string[] str1 = reader.ReadLine().Split();
 
            for (int i = 0; i < N; i++)
            {
                num[int.Parse(str1[i])+10_000_000]++;
            }
 
            int M = int.Parse(reader.ReadLine());
 
            string[] str2 = reader.ReadLine().Split();
 
            for (int j = 0; j < M; j++)
            {
                sb.Append(num[int.Parse(str2[j]) + 100_00_000] + " ");
            }
 
            print.WriteLine(sb);
        }
    }
}
cs
그리고 내가 문제를 너무 무식하게 푼건가 싶어서 찾아보다가 알아낸 불편한 진실.
문제 유형에 이분탐색이 써있길래 이분탐색을 사용했는데 (시간복잡도: nlogn)
알고보니 인덱스 번호를 가지고 직접 접근하면 됐다... (시간복잡도: n)

 

 

2024-03-23 00:28:33

첫째 줄에 반복횟수가, 둘째 줄부터는 x, y좌표가 문자열 형식으로 한 줄로 입력된다.

좌표 정렬하기(1) 문제와는 조금 다르게 y좌표를 우선적으로 정렬하고, x좌표를 정렬하는 문제이다

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //using var reader = new StreamReader(Console.OpenStandardInput());
            //using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            List<Tuple<intint>> list = new List<Tuple<intint>>();
 
            int N = int.Parse(Console.ReadLine());
            string[] str;
 
            for (int i = 0; i < N; i++)
            {
                str = Console.ReadLine().Split();
                list.Add(new Tuple<intint>(int.Parse(str[1]), int.Parse(str[0])));
            }
            list.Sort();
 
            foreach (Tuple<intint> a in list)
            {
                sb.Append(a.Item2 + " " + a.Item1 + "\n");
            }
 
            Console.WriteLine(sb);
        }
    }
}
cs

뭐 대단한 알고리즘이 떠오르지 않아서 그냥 리스트에 튜플 형식으로 넣어줄 때 x좌표와 y좌표의 순서를 바꿔서 넣었고, 출력할때는 다시 반대로 x좌표, y좌표 순서대로 출력해주었다.

2024-03-23 00:07:41

첫째 줄에는 참가 인원 수, 커트라인이 문자열 형식으로 한 줄로 주어지고

둘째 줄에는 각 참가자들의 점수가 주어진다.

참가자 중 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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            //StringBuilder sb = new StringBuilder();
 
            string[] input = reader.ReadLine().Split();
            int N = int.Parse(input[0]);
            int cut = int.Parse(input[1]);
 
            string[] getScore = reader.ReadLine().Split();
            int[] score = new int[N];
 
            for (int i = 0; i < N; i++)
                score[i] = int.Parse(getScore[i]);
 
            Array.Sort(score);
            Array.Reverse(score);
 
            print.WriteLine(score[--cut]);
        }
    }
}
cs

순위를 내림차순 정렬을 한 후, 주어진 커트라인을 이용해 인덱싱을 한다.

참고로 배열은 0번부터 시작하므로 커트라인을 1 감소시켜줘야 한다.

내가 사용한 방법은 데이터의 값을 변형시키므로 코드를 다시 사용해야 할 경우 문제가 될 수 도 있다.

 

또 다른 방법으로는 그냥 score.Length - cut 을 하면 내림차순 정렬을 할 필요가 없다.

 

2024-03-22 00:31:12

첫째 줄에는 몇명의 회원이 등록했는지 입력이 주어진다.

둘째 줄부터는 회원의 나이, 이름이 한 줄에 띄워쓰기로 구분되어 주어진다.

주어진 회원들을 나이 -> 회원 가입 순서대로 정렬하면 된다.

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            List<Tuple<intintstring>> list = new List<Tuple<intintstring>>();
 
            int N = int.Parse(Console.ReadLine());
            string[] mem;
            int count = 0;
 
            for (int i = 0; i < N; i++)
            {
                count++;
                mem = Console.ReadLine().Split();
                list.Add(new Tuple<intintstring>(int.Parse(mem[0]), count, mem[1]));
 
            }
            list.Sort();
 
            foreach (Tuple<intintstring> a in list)
                sb.Append(a.Item1 + " " + a.Item3 + "\n");
 
            Console.Write(sb);
 
        }
    }
}
cs

주어진 입력은 나이, 이름 뿐이라 가입 순서를 간과할 수 도 있다.

실제로는 이름은 사실상 허수고, 나이와 가입 순서로 정렬을 하기 때문에, 보이지 않는 값인 등록 순서를 넣어주는 것이 핵심인 것 같다.

리스트에 튜플을 <int, int, string>(나이, 가입순서, 이름> 순으로 받아와서, 정렬을 해준다.

c#에서 지원하는 자동 정렬 메서드는 튜플에 입력된 아이템 순서대로 정렬을 해주기 때문에, 이름이 두번째 아이템으로 오게 된다면 예제에서 준규와 동현의 순서가 바뀌어서 출력 될 것이다.

또 하나 알아낸 점이 있는데, StreamWriter나 StreamReader를 사용 할 때에, 모든 입/출력을 통일하지 않으면 vs환경에서는 딱히 오류 없이 진행되나, 백준에서 검사할 때는 런타임 에러(Format) 이뜨게 되는 것 같다.

뭐든지 통일이 중요하다 싶다.

2024-03-22 00:09:58

첫번째 줄에 띄어쓰기 없이 숫자가 주어진다.

주어진 수를 오름차순 정렬이 아닌, 내림차순 정렬을 해서 띄어쓰기 없이 한 줄로 출력하면 된다.

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
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection.PortableExecutable;
 
namespace 연습장
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var reader = new StreamReader(Console.OpenStandardInput());
            using var print = new StreamWriter(Console.OpenStandardOutput());
            StringBuilder sb = new StringBuilder();
 
            string str = reader.ReadLine();
            int[] Dec = new int[str.Length];
 
 
            for(int i = 0; i < str.Length; i++)
            {
                Dec[i] = str[i] - '0';
            }
 
            for(int j=0; j<Dec.Length; j++)
            {
                int temp = 0;
                for(int k=j; k<Dec.Length; k++)
                {
                    if (Dec[j] < Dec[k])
                    {
                        temp = Dec[k];
                        Dec[k] = Dec[j];
                        Dec[j] = temp;
                    }
                }
            }
            foreach (int a in Dec)
                sb.Append(a);
 
            print.Write(sb);
 
        }
    }
}
cs

이번 문제는 내림차순을 구현하는 문제이다.

비록 Array.sort(Dec); Array.Reverse(Dec); 혹은

Dec = Dec.OrderByDesCending(x => x).ToArray(); 메소드를 사용해서 구현할 수 있겠지만,

이번 문제의 핵심은 지금까지는 오름차순을 사용했겠지만 이번엔 "직접 내림차순을 구현해 봐라"

라는 의미로 와닿아서 직접 구현을 해봤다.