Problem #011
✏️ 𝗔𝗹𝗴𝗼𝗿𝗶𝘁𝗵𝗺/etc

Problem #011

오일러 알고리즘

🚩 문제 설명

오일러 알고리즘 #011

◾ 20 x 20 격자에서 연속된 네 숫자의 곱들 중 최댓값을 구하는 문제

◾ 위와 같이 20길이의 정사각형 격자가 주어진다.

◾ 연속된 수를 곱할 때, 방향은 아래와 같다.

  • 수평
  • 수직
  • 오른쪽 대각선
  • 왼쪽 대각선

◾ 각 수자는 2자리 숫자

 

 


 

 

📑 문제 풀이

#include <iostream>
using namespace std;

// 보기좋게 tab을 한것이니 코드 돌려볼때는 붙여놓기
string str = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\n
              49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\n
              81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\n
              52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\n
              22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\n
              24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\n
              32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\n
              67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\n
              24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\n
              21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\n
              78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\n
              16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\n
              86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\n
              19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\n
              04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\n
              88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\n
              04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\n
              20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\n
              20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\n
              01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";

unsigned long long arr[401]; / 수를 저장할 배열 초기화

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	int num;
	int index = 0;

	// 배열에 수 저장
	for (int i = 0; i < str.size(); i+=3)		
	{
		num = 10 * (str[i] - '0') + (str[i + 1] - '0');
		arr[index++] = num;
	}

	// 수평 max 구하기
	long long max = 0;								
	for (int i = 0; i < 397; i++)				
	{
		long long sum = 1;

		if (i % 20 == 17) i = i+3;

		for (int j = i; j <= i + 3; j++)
		{
			sum *= arr[j];
		}
		if (max < sum) max = sum;
	}
	cout << "수평 max: " << max << '\n';
    
    
	// 수직 max 구하기
	max = 0;									
	for (int i = 0; i < 340; i++)				
	{
		long long sum = 1;
		
		for (int j = i; j < i+80; j += 20)
		{
			sum *= arr[j];
		}
		if (max < sum) max = sum;
	}
	cout <<"수직 max: " << max << '\n';
    
	
    // 오른쪽 대각선 max 구하기
	max = 0;									
	for (int i = 0; i < 337; i++)
	{
		long long sum = 1;

		if (i % 20 == 17) i = i + 3;

		sum = sum * arr[i] * arr[i + 21] * arr[i + 42] * arr[i + 63];

		if (max < sum) max = sum;
	}
	cout << "오른쪽 대각선 max: " << max << "\n";

	
    // 왼쪽 대각선 max 구하기
	max = 0;									
	for (int i = 0; i < 337; i++)
	{
		long long sum = 1;

		if (i % 20 == 19) i = i + 4;

		sum = sum * arr[i+3] * arr[i + 22] * arr[i + 41] * arr[i + 60];

		if (max < sum) max = sum;
	}
	cout << "왼쪽 대각선 max: " << max << "\n\n";
	return 0;
}

💬 Point

👉 방향마다 최대값 구해주기

◾ 주어진 격자를 배열로 만들어준다.

  • 각 숫자는 두자리 이므로 10 * (10의 자리) + (1의 자리) 이런식으로 숫자를 만들어 배열에 넣는다.
  • 중간에 빈칸이 있으므로 세칸씩 이동한다.
  • 한가지 주의점은 필자는 2차원 배열이 아닌 1차원 배열을 사용했다.

◾ 각각의 방향에 따라 max를 구했다.

◾ 수평 최대값을 구하는 로직

  • 이는 쉽다.
  • 반복문을 두 개 돈다.
  • 첫번째 반복문은 1 ~ 396까지 돌면 된다.
  • 두번째 반복문은 해당 숫자에서부터 4번만 돈다.
  • 그리고 연속적인 수들을 sum 변수에 더해준다. 

◾ 수직 최대값을 구하는 로직

  • 수직은 세로를 생각해야한다.
  • 그래서 20씩 스텝을 둬야한다.
  • 그리고 반복문은 해당 수에서 + 80만큼 돈다.
  • 왜냐하면 20씩 스텝이 돌기때문에 20, 40, 60, 80 이런식으로 움직여야하기 때문이다.

◾ 오른쪽 대각선 최대값을 구하는 로직

오른쪽 대각선

  • 그림판으로 그려서 좀 볼품없지만 이해해주시길 ^^;
  • 이런식으로 대각선이 만들어져야하는데 만약 대각선의 첫번째가 1이라고 가정하고
  • 일반화를 시켜보면
  • 두번째 요소는 22번째에 해당한다.
  • 세번째 요소는 43번째에 해당한다.
  • 네번째 요소는 64번째에 해당한다.
  • 하지만 배열은 0부터 시작하므로 하나씩 빼보면 i+21, i+42, i+63에 해당하는 것을 알 수 있다.
  • 해당 수들을 구해서 sum 변수에 곱해주면 된다.
  • 반복문이 337 아래로 돌아가는 이유는 336 + 63 = 399 가 되기 위해서이다.

◾ 왼쪽 대각선 최대값을 구하는 로직

  • 왼쪽 대각선도 오른쪽과 마찬가지로 구한다.

 

 


 

 

But,

✅ 2차원 배열로 왜 안풀었지 라는 생각이 들긴하다.
✅ 하지만 시간복잡도가 O(N^2)로 늘어날 것이다.
✅ 푸는 데 시간을 오래 잡아먹었다.
✅ 허나, 오른쪽 대각선을 완성하니 왼쪽 대각선은 쉬이 만들어졌다.
✅ sum과 max는 범위를 long long으로 주는 것을 잊지말것..

➕ 풀이 사이트 첨부

https://www.mathblog.dk/greatest-product-in-20x20-grid/

 

Solution to Project Euler problem 11 in C# | MathBlog

I consider Problem 11 of Project Euler to be a problem where brute force search is the only solution. The problem reads What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20*20 grid? Basical

www.mathblog.dk

 

 

 

 

 

 

 

 

 

 


 

728x90

'✏️ 𝗔𝗹𝗴𝗼𝗿𝗶𝘁𝗵𝗺 > etc' 카테고리의 다른 글

Problem #014  (0) 2020.02.05
Problem #013  (0) 2020.02.04
Problem #010  (0) 2020.01.30
Problem #008  (0) 2020.01.28
Problem #006  (0) 2020.01.21