15개의 댓글이 있습니다.
-
-
Sharifa -
play(0)할 때 cout << tileSize << endl;만 추가하셔도 알 겁니다.
tileSize가 오로지 R로만 저장되는군요.
tileSize가 실제 크기에 비해 대부분의 경우 훨씬 작을 수밖에 없는 행의 크기로 측정되니 당연히 오래 걸리죠.
그것만 바꾸면 몇 초 안에 잘 나옵니다.
제 코드보다 약간 느리긴 한데 그건 함수별 수행 시간의 차이라고 추측되고요//여기서부터는 일종의 최적화
최초의 빈 칸이 어디 있는지 탐색할 때 굳이 처음부터 돌 필요 없습니다.
이전에 i_before에서 빈 칸을 찾아서 play를 수행했다면,
다음부터는 i_before+1부터 탐색해도 됩니다.
그리고 매번 H*W를 계산하는데 한 테스트 케이스에서 그 값은 일정하니까 굳이 계속 계산할 필요 없습니다.
곱셈은 시간이 많이 소요되는 연산입니다(괜히 karatsuba 알고리즘이 있는게 아닙니다)그리고..부탁인데(?) 코드는 이렇게 짜지 않았으면 합니다.
정말 읽기 싫게 생겼습니다.
아마 코딩의 편의를 위해 수많은 #define문을 비롯 엄청난 수의 문장들이 들어가 있는데
이 문제와는 관련 없는 코드가 100줄은 됩니다.
10년 전 link
-
-
-
Sharifa -
또 하나 최적화 방법을 말해드리자면
1
10 10 1 2
"..#...#...
"...#.#.#..
"#.#.#...#.
".#...#.#.#
"..#.#.#...
".#.#...#..
"#...#.#.#.
".#.#.#...#
"..#...#.#.
"...#...#..
"##
이런 데이터를 한번 넣어보세요.
시간 안에 안 나온다면, 분리된 공간을 각각 탐색한 후 각 공간에서 최댓값을 더하는 방법을 쓰면 훨씬 빨라질 겁니다.
//참고로 위 데이터에서 제일 많이 채울 수 있는 경우의 수만 해도 5억 가지가 넘습니다
10년 전 link
-
-
-
Being -
- 친절한 답변에 감사드립니다. 몇 가지만 짚고 넘어가겠습니다.
- H*W의 곱셈으로 느려졌다는 건 넌센스입니다.
- 어디서부터 탐색할지 위치를 저장하는 것이 큰 성능 향상을 가져다 주지는 않을 것입니다. 선형적인 영향을 줄 뿐이죠. 가지치기는 지수적인 영향을 미치므로 여기에 묻힐 수밖에 없습니다.
- 다른 분의 코드에 조언을 하실 때에는 서로 존중하는 분위기에서 했으면 좋겠습니다. 코드에 개선의 여지가 많기는 하지만, 올림피아드나 ICPC와는 달리 탑코더 등에서는 미리 준비한 코드를 허용하므로 저런 매크로 등을 활용하는 참가자들도 상당수임을 인지하셨으면 합니다.
10년 전 link
-
-
-
Being -
- 그래서 그 두 배 빠르고 느린 게 어떤 의미가 있나요? 질문자님께서는 '1000배' 가량 빨라져야 할 것 같다고 판단하고 계시는데요.
- 시간에 가장 큰 영향을 미치는 것이
play()
내부의 루프들이니만큼, 마지막 탐색 위치를 기억하는 것은 당연히 변의 길이에 비례한 성능 향상을 기대할 수 있습니다. 이 부분은 제가 선형적인 영향을 준다고 이미 말씀드린 바 있습니다. - H*W의 곱셈 결과를 미리 계산해 두는 것은 정말 전혀 영향을 미치지 않습니다. 더욱이, 탐색 위치를 저장한다면 곱셈 결과를 활용하는 가장 바쁜 곳이 사라지기까지 하지요. 이유는 다음과 같습니다.
- 곱셈 인스트럭션은 비싸지 않습니다. 메모리 액세스에 비하면 아무 것도 아니지요. 카라츠바의 케이스는, 큰 정수를 곱셈할 때에는 효율적인 방법이 필요함을 나타낼 뿐입니다.
- 웬만한 컴파일러는 H*W가 불변이므로 루프 밖으로 꺼냅니다.
10년 전 link
-
-
-
Taeyoon_Lee -
사실 나도 도와주고 싶었지만.. 수많은 매크로에 패배함.
10년 전 link
-
-
-
Sharifa -
0.제 댓글이 마음에 안 드실 수는 있지만 그렇다고 해도 왜 저한테 시비조로 말씀하시는지 모르겠습니다.
1.1000배가량 빨라질 수 있도록 오류를 정정해드렸습니다. 저는 중요한 것은 놔두고 중요하지 않은 것만 강조하는 게 아닙니다.
1.이 문제는 최적화 문제이기도 한데 두 배의 시간 차이가 의미가 없다고 할 수는 없습니다. 1000배에 비해서는 1%도 되지 않지만, 그렇다고 의미가 없는 건가요?
1.그리고 저는 질문과는 별개로 많은 경우에 대해 1000배 이상의 효과를 낼 수 있는 방법도 말한 걸로 아는데요.
3. H*W를 미리 계산하는 것은 사실 컴퓨터 상황에 따른 수행 시간의 오차보다도 작을 것이고 따라서 크게 차이가 없을 것이라는 건 맞습니다.
3-1.곱셈이 메모리 액세스에 비하면 아무 것도 아니라고 하셨는데, 그 말은 H*W를 참조할 때는 메모리에 액세스하고 H와 W를 참조할 때는 아니라는 것처럼 들립니다.
3-1.HW가 캐시에 들어갈 지는 모르겠지만, 캐시에 의해서는 메모리 액세스 비용이 생각하시는 만큼 비싸지는 않습니다.
3-1.애초에 곱셈이 덧셈만큼 컴퓨터에서 빠르게 수행된다면 카라츠바 알고리즘은 아무런 쓸모도 없었을 겁니다. 카라츠바는 곱셈은 확실히 줄였지만, 총 연산 수는 더 많습니다.
10년 전 link
-
-
-
Being -
일단 감정을 좀 가라앉히시고 이야기하시죠.
- 저는 가장 중요한 부분을 짚어주신 데에 대해 인정합니다. 이견의 여지 없이 훌륭한 지적이었습니다. 이 부분에 있어서 제가 불만을 표현한 적은 없습니다만, 그렇게 느끼셨다니 제 표현 방법에 문제가 있었던 모양입니다. 사과드립니다.
- 나머지 두 부분에 있어서는, 논란의 여지가 있어 지적하고자 했습니다.
- H*W 곱셈의 경우
- H*W, H, W를 저장한 변수가 메모리에 있든 없든 캐시에 있든 없든, 곱셈을 직접 하건 저장하건 그것들은 성능에 영향을 거의 미치지 않습니다. 왜냐하면 다른 훨씬 느린 인스트럭션들이 함수 내에 많기 때문입니다. 메모리 액세스는 H, W, H*W에 대한 이야기가 아니라 코드 내에서 메모리를 참조하는 다른 수많은 부분들에 대한 언급입니다.
- 저 답변을 다는 시점에 혹여나 성능에 영향을 미칠지 모르겠다 생각되어 H*W의 값을 저장하여 테스트해보았으며, 전혀 영향을 미치지 않음을 확인하였습니다.
- 카라츠바는 지금 논의에 전혀 무관하니 자꾸 이야기 나오지 않았으면 합니다.
- 곱셈이 느려서 써서는 안 된다! 라고 하실 정도면 배열 크기를 전부 2의 거듭제곱으로 잡고 오프셋 계산을 bitwise 연산 하셔야 합니다.
- 마지막 위치를 기억하는 것: 다시금 언급하지만 분명히 성능 향상이 있으나 그 향상량이 문제와 질문자님 의도에 비추어 미미함을 지적하고자 했습니다.
- H*W 곱셈의 경우
10년 전 link
-
-
-
Sharifa -
2.1.1 그렇다면 제가 무엇에 대한 메모리 액세스에 대한 말인지 잘 몰라서 잘못 답을 한 것 같군요.
2.1.2 제가 테스트한 바로는 약간 느렸습니다. 하지만 위에서도 언급했던 것처럼 컴퓨터 상황에 따른 오차보다 작을 것이고 큰 효과가 없음은 이미 말했습니다. 저는 지금 H*W가 효과가 크다고 말하고 있지 않습니다.
2.1.3 ..뭐 별 관련이 없긴 합니다만.
2.1.4 그 정도는 아닙니다. 곱셈이 자꾸 논란이 되는군요.
2.2 맞는 말입니다. 하지만 저는 질문자님의 의도에 맞는 답을 한 후 그 외에 향상할 수 있는 방법을 말해 본 것 뿐입니다. 이거야말로 왜 논란이 자꾸 되는지 모르겠군요.오해가 많았던 것 같은데 기분 나쁘신 것 있다면 사과드립니다.
정리하자면,
1. tileSize++문 실수가 가장 큰 원인
2. 마지막 탐색 위치 저장은 (질문의 의도와는 큰 상관 없지만)하나의 최적화 옵션
3. H*W는 별다른 효과 없음
정도 되겠군요.
10년 전 link
-
-
정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.
sven
안녕하세요, BOARDCOVER2 문제의 TLE 를 해결하기가 쉽지 않아 질문드립니다.
책의 풀이와 비교해서, bitset 을 사용하였고, 각각의 좌표에서 움직일 수 있는 가능성이 있는 좌표들을 미리 계산해두었다는 차이점이 있고, 나머지는 비슷한 것 같습니다.
10 10 3 3
..........
..........
..........
..........
..........
..........
..........
..........
..........
..........
".#."
"###"
"..#"
이런 인풋을 넣으면 오래 걸리는데요, 어떻게 개선하면 좋을지 잘 모르겠습니다. 계산 횟수의 upper limit 로, 가장 간단하게 4^(100/5) = 2^40 = 10^12 를 생각할 수 있습니다만, 가지치기를 통해서 실제로는 그보다 충분히 짧게 되리라고 생각했습니다. 시간을 어림하는 것도 개선하는 것도 감이 잘 오지 않습니다ㅜㅜ 조언 부탁드립니다.
10년 전