knight7024   6년 전

dp 행렬에서 i행과 j열이라고 했을 때, i는 자릿수이고 j는 맨 앞자리 수입니다.

(예를 들어 i가 4이고 j가 9이면 9000~9999인 셈)

1. 감소하는 수가 몇 개인지 자릿수와 맨 앞자리 수 별로 dp 행렬에 저장합니다.

2. 그 후 브루트포싱을 통해 N을 찾습니다.

(본문의 예시를 들면, 49까지의 감소수는 총 20개입니다. 총 감소수를 tempN이라고 하고 N은 18이므로 50부터 감소시키며 tempN도 감소시킵니다.)


생각나는 방법이 없어 이런 무식한 방식으로 풀어봤는데 2%에서 시간 초과가 납니다. ideone에서 컴파일 했을 때는 1000~1022까지 각각 모두 0.1s 이내로 출력되어서 자신있게 제출했는데 안되네요. 답은 모두 맞게 나오는 것 같습니다...

시간초과가 나는건지 어디서 무한루프가 걸리는건지 모르겠습니다..

제한시간 2초라는게 모든 테스트케이스 다 합쳐서 2초인가요..?

딱히 줄일 방법이 없다면 알고리즘을 새로 생각해보도록 하겠습니다. 의견 부탁드립니다..


dp는 이런식으로 저장됩니다. ▼
캡처.PNG



djm03178   6년 전

가상 머신으로 테스트 해봤는데 저도 잘 모르겠네요. 모든 가능한 입력을 돌려봐도 0.5초 이상 걸리는 건 없었던 것 같은데 뭔가 문제가 될 수 있는 다른 부분이 있는 건진 모르겠네요.

그리고 시간 제한은 단일 케이스에 대한 제한이 맞습니다.

knight7024   6년 전

ㅠㅠㅠㅠㅠㅠㅜ 6시간 이상 봤는데도 모르갰어요 단일 제한이 맞는데 왜 틀리는거죠 ㅠㅠㅠㅠㅠㅠ 혹시 아시는 분 제발 도움 부탁드립니다

doju   6년 전

N에 충분히 큰 값이 입력되어서 32번째 줄까지의 반복문을 전부 돌고 나오면 i는 11, j는 10이 됩니다. 그러면 34번째 줄에서 dp[11][10]을 참조하게 되는데, 이 위치는 원래 선언된 dp 배열의 범위를 벗어나므로 undefined behavior가 일어납니다.
운이 좋아서 dp[11][10]이 0으로 취급되었다면 -1이 출력되겠지만, 그렇지 않으면 39번째 줄을 실행하게 될 것입니다.

i = 11, j = 10인 상황에서 (j + 1) * pow(10, i - 1) - 1 을 계산하면 109999999999.000000입니다. pow는 항상 실수 값을 리턴합니다.
물론 저렇게 큰 수가 나오는 시점에서 시간 초과를 예상할 수 있겠지만, 심지어 여기서 int 변수가 담을 수 있는 범위를 넘어가는 실수 값을 int 변수에 캐스팅하기 때문에 한 번 더(!) undefined behavior가 일어납니다.

제가 사용하는 환경에서는 위의 시나리오대로 프로그램이 실행되었고, k에 -2147483648이 들어가서 examination 함수를 111.4억 번 호출한 뒤 -2146482626라는 값이 출력되었습니다.

knight7024   6년 전

@doju 님 정말 정말정말정말 정말 미친듯이 감사드립니다. 기쁨을 주체할 수가 없습니다. DP 행렬을 0으로 초기화 시켜놨었고 VS 환경에서는 배열 범위 넘은건 알아서 0으로 초기화 해주는 환경이기에 전혀 신경쓰지 못했습니다. 정말 친절하고 자세한 설명에 몸둘 바를 모르겠습니다.

아래 소스로 바꾸어서 해결했습니다. 드디어 12시간 만에 해결봤습니다. 정말 감사드립니다. 어떻게 표현이 불가능합니다.............

djm03178   6년 전

헉 저걸 놓쳤군요

왜 저걸 못 봤을까요 ㅠ

knight7024   6년 전

@djm03178 님도 도와주셔서 감사드립니다. 여러분들 덕분입니다....

댓글을 작성하려면 로그인해야 합니다.