다양한 저장매체의 속도를 측정

 1. Cache와 main memory의 속도 비교:

Array에 data를 access하는 시간을 통해 비교하였다.

Array는 메모리에 연속적으로 할당이 되고, Array에 data를 access할 때 일정 크기만큼 cache에 올라가기 때문에 array 순서대로 참조할 경우 cache에 올라간 값을 access 한다. 하지만 비연속적인 참조를 할 경우 cache에 올라간 값이 아니기 때문에 main memory에 access하게 된다.

 

windows 버전

 

ContractedBlock.gifExpandedBlockStart.gifCode
#include <stdio.h>
#include <time.h>
#include <windows.h>

#define SIZE 10000
#define CHECK_TIME_START QueryPerformanceFrequency ((_LARGE_INTEGER*)&freq); QueryPerformanceCounter((_LARGE_INTEGER*)&start)
#define CHECK_TIME_END(a) QueryPerformanceCounter((_LARGE_INTEGER*)&end); a=(float)((float) (end - start)/freq)

int a[SIZE][SIZE];

void main() {

    __int64 start, freq, end;
    
float resultTime=0;
    printf("시작\n");
    CHECK_TIME_START;  
  
    
for(int i=0;i<SIZE;i++){
        
for(int j=0;j<SIZE;j++){
            a[j][i] = 0;
        } 
    }
    CHECK_TIME_END(resultTime);

    printf("끝 %f ",resultTime);

    CHECK_TIME_START;  
    
    
    
for(int i=0;i<SIZE;i++){
        
for(int j=0;j<SIZE;j++){
            a[i][j] = 0;
        } 
    }
    CHECK_TIME_END(resultTime);

    printf("끝 %f ",resultTime);
}

 

 리눅스 버전:

 

ContractedBlock.gifExpandedBlockStart.gifCode
 #include <stdio.h>
//#include <time.h>
//#include <windows.h>
#include <sys/time.h>

#define SIZE 10000

long timecacul () {
        
struct timeval tv;
        
struct timezone tz;
        gettimeofday(&tv,&tz);
        
return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}

int a[SIZE][SIZE];

void main() {
    
    
long starttime, endtime, resultTime;
    
int i, j;

    printf("시작\n");
      starttime = timecacul ();

    
for(i=0;i<SIZE;i++){
        
for(j=0;j<SIZE;j++){
            a[j][i] = 0;
        } 
    }
    endtime = timecacul ();
    resultTime = endtime -starttime;

    printf("끝 %ld ",resultTime);

      starttime = timecacul ();
    
    
    
for(i=0;i<SIZE;i++){
        
for(j=0;j<SIZE;j++){
            a[i][j] = 1;
        } 
    }

    endtime = timecacul ();
    resultTime = endtime -starttime;

    printf("끝 %ld ",resultTime);
}

 

소스 코드 설명

10000 x 10000의 배열에 0을 넣는 시간을 측정한다. 두 가지 방법으로 넣는데, 위쪽 for loop 에서는 메모리에 비연속적으로 0을 넣고 있고(a[j][i] = 0;) 아래쪽 for loop에서는 메모리에 연속적으로 0을 넣고 있다 (a[i][j] = 0;).

 

Ubuntu9.10에서 돌린 결과:

 

rize@rize-laptop:~/end$ ./os
시작
끝 5334 끝 414

 

2. main memory 와 Magnetic disk의 속도 비교:

Sqlite디비를 메인 메모리와 하드 디스크에서 돌려서 시간 측정한다.

 

 

 

 

转载于:https://www.cnblogs.com/jinrize/archive/2009/11/23/1608570.html

당신은 순서대로 개의 퍼즐을 제한 시간 내에 풀어야 하는 퍼즐 게임을 하고 있습니다. 각 퍼즐은 난이도와 소요 시간이 정해져 있습니다. 당신의 숙련도에 따라 퍼즐을 풀 때 틀리는 횟수가 바뀌게 됩니다. 현재 퍼즐의 난이도를 , 현재 퍼즐의 소요 시간을 , 이전 퍼즐의 소요 시간을 , 당신의 숙련도를 이라 하면, 게임은 다음과 같이 진행됩니다.ndifftime_curtime_prevlevel diff ≤ 이면 퍼즐을 틀리지 않고 만큼의 시간을 사용하여 해결합니다.leveltime_cur diff > level이면, 퍼즐을 총 - 번 틀립니다. 퍼즐을 틀릴 때마다, 만큼의 시간을 사용하며, 추가로 만큼의 시간을 사용해 이전 퍼즐을 다시 풀고 와야 합니다. 이전 퍼즐을 다시 풀 때는 이전 퍼즐의 난이도에 상관없이 틀리지 않습니다. - 번 틀린 이후에 다시 퍼즐을 풀면 만큼의 시간을 사용하여 퍼즐을 해결합니다.diffleveltime_curtime_prevdiffleveltime_cur 예를 들어 = 3, = 2, = 4인 경우, 에 따라 퍼즐을 푸는데 걸리는 시간은 다음과 같습니다.difftime_curtime_prevlevel level = 1이면, 퍼즐을 3 - 1 = 2번 틀립니다. 한 번 틀릴 때마다 2 + 4 = 6의 시간을 사용하고, 다시 퍼즐을 푸는 데 2의 시간을 사용하므로 총 6 × 2 + 2 = 14의 시간을 사용하게 됩니다. level = 2이면, 퍼즐을 3 - 2 = 1번 틀리므로, 6 + 2 = 8의 시간을 사용하게 됩니다. level ≥ 3이면 퍼즐을 틀리지 않으며, 2의 시간을 사용하게 됩니다. 퍼즐 게임에는 전체 제한 시간 가 정해져 있습니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 구하려고 합니다. 난이도, 소요 시간은 모두 양의 정수며, 숙련도도 양의 정수여야 합니다.limit 퍼즐의 난이도를 순서대로 담은 1차원 정수 배열 , 퍼즐의 소요 시간을 순서대로 담은 1차원 정수 배열 , 전체 제한 시간 이 매개변수로 주어집니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 정수로 return 하도록 solution 함수를 완성해 주세요.diffs times limit
最新发布
08-14
<think>우리는 이진 탐색을 사용하여 숙련도(level)의 최솟값을 찾을 수 있습니다. 조건: diff <= level 이면, time_cur 만큼의 시간이 소요. diff > level 이면, (diff - level) 번 틀리고, 각 틀릴 때마다 (time_cur + time_prev)의 시간이 소요되고, 마지막에 time_cur이 소요됨. 따라서 총 시간 = (diff - level) * (time_cur + time_prev) + time_cur 하지만 주의: 첫 번째 퍼즐의 경우 이전 퍼즐이 없습니다. 문제에서 "이전 퍼즐"은 두 번째 퍼즐부터 적용됩니다. 따라서 첫 번째 퍼즐은 어떻게 처리해야 할까? 문제 설명에 따르면, 첫 번째 퍼즐을 풀 때 이전 퍼즐이 없습니다. 조건을 보면: diff > level 인 경우, 틀릴 때마다 time_cur (현재 퍼즐의 시간)과 time_prev (이전 퍼즐의 시간)을 소모하며 이전 퍼즐을 다시 풀고 와야 한다. 그러나 첫 번째 퍼즐에는 이전 퍼즐이 없으므로, 이전 퍼즐을 다시 풀 수 없습니다. 문제를 다시 읽어보면, 예시에서 첫 번째 퍼즐에 대한 언급이 없습니다. 입력은 배열로 주어지므로, 첫 번째 퍼즐은 어떻게 처리해야 할까? 문제의 조건: "이전 퍼즐을 다시 풀 때는 이전 퍼즐의 난이도에 상관없이 틀리지 않습니다." 하지만 첫 번째 퍼즐은 이전 퍼즐이 없기 때문에, 첫 번째 퍼즐을 풀 때는 이전 퍼즐을 다시 풀 수 없습니다. 따라서 첫 번째 퍼즐에 대해서는 diff > level 인 경우에도 이전 퍼즐을 다시 풀 수 없다는 점을 고려해야 합니다. 그러나 문제에서 첫 번째 퍼즐에 대한 특별한 규정을 언급하지 않았습니다. 예시에서는 첫 번째 퍼즐이 아닌 경우를 설명하고 있습니다. 다시 문제를 보면, "현재 퍼즐"과 "이전 퍼즐"이라는 용어를 사용하고 있으므로, 첫 번째 퍼즐은 이전 퍼즐이 없으므로, 첫 번째 퍼즐을 풀 때는 오직 현재 퍼즐의 난이도와 숙련도만 비교해야 합니다. 문제의 조건을 첫 번째 퍼즐에 적용해보면: diff ≤ level: time_cur 만큼 시간 소요. diff > level: (diff - level) 번 틀리게 되지만, 이전 퍼즐이 없으므로 time_prev를 사용할 수 없습니다. 문제에서 이전 퍼즐의 소요 시간(time_prev)을 사용하라고 했지만, 첫 번째 퍼즐에서는 time_prev가 존재하지 않습니다. 따라서, 첫 번째 퍼즐에 대해서는 이전 퍼즐을 다시 풀 수 없으므로, 틀릴 때마다 추가적인 time_prev를 사용하지 못할 것입니다. 하지만 문제의 예시에서는 첫 번째 퍼즐이 아닌 경우를 설명하고 있습니다. 우리는 첫 번째 퍼즐을 어떻게 처리해야 할지 문제의 조건에서 명시적으로 알 수 없습니다. 이에 대한 해석이 필요합니다. 문제의 조건을 보면, "이전 퍼즐을 다시 풀고 와야 합니다" 라고 했으므로, 첫 번째 퍼즐에서는 이전 퍼즐이 없기 때문에 틀렸을 때 이전 퍼즐을 다시 풀 수 없습니다. 따라서 첫 번째 퍼즐은 무조건 한 번에 맞춰야 한다고 해석할 수 있습니다. 또는, 첫 번째 퍼즐에서는 이전 퍼즐이 없으므로 time_prev를 0으로 간주할 수 있을까요? 문제에서 주어진 매개변수는: diffs: 퍼즐의 난이도 배열 (길이 n) times: 퍼즐의 소요 시간 배열 (길이 n) limit: 전체 제한 시간 그리고 첫 번째 퍼즐의 이전 퍼즐은 존재하지 않습니다. 문제를 해결하기 위해 다음과 같이 가정합니다: 첫 번째 퍼즐 (i=0)을 풀 때: if diff[0] <= level: 시간 = times[0] else: # diff[0] > level 인 경우, 틀린 횟수 = diff[0] - level # 하지만 이전 퍼즐이 없으므로, time_prev를 0으로 생각해야 할까? # 문제에서 "이전 퍼즐의 소요 시간"을 사용하라고 했지만, 없으므로 0으로 처리하면? # 그러면 틀릴 때마다 (times[0] + 0) = times[0]이 소요되고, 마지막에 times[0]이 소요됨. # 따라서 총 시간 = (diff[0]-level)*times[0] + times[0] = (diff[0]-level+1)*times[0] 두 번째 퍼즐부터 (i>=1): if diff[i] <= level: 시간 = times[i] else: 시간 = (diff[i]-level)*(times[i] + times[i-1]) + times[i] 하지만 예시에서 첫 번째 퍼즐에 대한 언급이 없으므로, 이 가정을 검증할 수 없습니다. 그러나 문제의 예시 입력이 주어지지 않았으므로, 문제의 설명에 따라 일반화해야 합니다. 문제를 출제한 의도로 보아, 첫 번째 퍼즐에 대해서는 이전 퍼즐이 없으므로, 틀렸을 때 이전 퍼즐을 다시 풀지 않아도 된다고 하면 안됩니다. 오히려 첫 번째 퍼즐을 틀리면 이전 퍼즐이 없기 때문에 다시 풀 수 없으므로, 첫 번째 퍼즐은 무조건 한 번에 맞춰야 한다고 생각할 수 있습니다. 하지만 문제에서 숙련도를 최소화하면서 제한 시간 내에 풀어야 하므로, 첫 번째 퍼즐도 숙련도가 낮으면 틀릴 수 있다고 가정해야 합니다. 문제의 조건을 재해석: "퍼즐을 틀릴 때마다, 만큼의 시간을 사용하며, 추가로 만큼의 시간을 사용해 이전 퍼즐을 다시 풀고 와야 합니다." -> 이전 퍼즐이 없으면, "이전 퍼즐을 다시 풀고 오는" 과정이 불가능합니다. 따라서 첫 번째 퍼즐은 틀리면 안 됩니다. 즉, 첫 번째 퍼즐은 숙련도가 난이도보다 높아서 틀리지 않아야 합니다. 하지만 숙련도의 최솟값을 구하는 문제이므로, 첫 번째 퍼즐의 난이도가 높을 경우 숙련도를 높여야 합니다. 하지만 이렇게 되면 첫 번째 퍼즐은 무조건 diff[0] <= level 이어야 합니다. 만약 level이 diff[0]보다 작으면 첫 번째 퍼즐을 풀 수 없게 됩니다. 그러나 문제의 조건에서는 숙련도를 선택할 수 있고, 우리가 구하려는 숙련도의 최솟값이므로, 첫 번째 퍼즐의 난이도 diff[0]보다 적어도 level이 diff[0] 이상이어야 합니다. 하지만 두 번째 퍼즐부터는 이전 퍼즐이 있으므로 level이 더 낮아도 틀릴 수 있습니다. 따라서 첫 번째 퍼즐에 대해서는: 무조건 diff[0] <= level 이어야 하므로, 시간은 times[0] 만 소요됩니다. 이 가정을 바탕으로 하면, 첫 번째 퍼즐은 항상 한 번에 풀립니다. 하지만 문제에서 주어진 예시는 첫 번째 퍼즐이 아닌 경우를 설명하고 있으므로, 이렇게 해석하는 것이 합리적입니다. 따라서 전체 퍼즐을 푸는 총 시간: time_total = time0 + time1 + ... + time_{n-1} where time0 = times[0] (첫 번째 퍼즐은 무조건 한 번에 풀리므로) for i from 1 to n-1: if diffs[i] <= level: time_i = times[i] else: time_i = (diffs[i] - level) * (times[i] + times[i-1]) + times[i] 이제 우리는 level의 최솟값을 찾아야 합니다. level은 적어도 첫 번째 퍼즐의 난이도 diff[0] 이상이어야 합니다. level의 하한: 1 (양의 정수) level의 상한: max(diffs) (모든 퍼즐의 난이도 중 최댓값) -> 왜냐하면 level이 max(diffs)가 되면 모든 퍼즐에 대해 diff[i] <= level이 성립하므로, 총 시간은 단순히 times 배열의 합이 됩니다. 따라서 level의 범위: [1, max_diff] (max_diff = max(diffs)) 하지만 첫 번째 퍼즐을 고려하면 level은 최소한 diff[0] 이상이어야 합니다. 그러나 level이 diff[0]보다 작을 수는 없습니다. (첫 번째 퍼즐을 풀 수 없으므로) 따라서 level의 하한: max(1, diff[0])? 하지만 두 번째 퍼즐부터는 level이 작아도 풀 수 있으므로, 첫 번째 퍼즐을 풀기 위해 level >= diff[0]이 필요합니다. 그러므로 level의 범위: [diff[0], max_diff] 단, diff[0]이 1보다 작을 수 없으므로 (양의 정수) [diff[0], max_diff] 하지만 만약 첫 번째 퍼즐의 난이도가 max_diff보다 클 수도 있습니다? 그런 경우는 없습니다. max_diff는 모든 난이도의 최댓값이므로, diff[0] <= max_diff입니다. 따라서 level을 diff[0]부터 max_diff까지 이진 탐색하면서, 총 시간이 limit 이하인지 확인합니다. 이진 탐색: low = diff[0] high = max_diff (max_diff = max(diffs)) while low <= high: mid = (low+high)//2 total_time = calc_time(mid) # mid level로 계산한 총 시간 if total_time <= limit: answer = mid high = mid - 1 # 더 작은 level을 시도 else: low = mid + 1 만약 [diff[0], max_diff] 범위 내에서 limit 이하를 만족하는 level이 없으면? 문제에서 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 구하는 것이므로, 만약 이 범위에서 조건을 만족하는 level이 없으면, 더 큰 level을 시도해야 할까? 하지만 level이 max_diff보다 커봤자, max_diff일 때와 동일하게 동작합니다. (level이 max_diff 이상이면 모든 퍼즐이 한 번에 풀리므로, 총 시간은 times의 합) 따라서 max_diff일 때 총 시간 = sum(times) 만약 sum(times) > limit 이면, 제한 시간 내에 풀 수 없는 경우가 됩니다. 문제의 return 조건: 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 정수로 return. 만약 제한 시간 내에 풀 수 없다면? 문제에서 명시하지 않았으므로, 우리는 항상 제한 시간 내에 풀 수 있는 경우만 입력으로 주어진다고 가정할 수 없습니다. 문제 조건: "제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값" -> 만약 불가능하다면? 문제에 따르지 않았으므로, 일단은 가능한 입력만 주어진다고 가정하거나, 불가능한 경우 -1을 반환하는 등의 처리가 필요할 수 있습니다. 하지만 문제의 제한 사항을 보지 못했으므로, 일단은 이진 탐색을 시도하고, [diff[0], max_diff] 범위에서 조건을 만족하는 level이 없으면, max_diff+1 이상의 level은 모두 max_diff일 때와 같은 총 시간을 가지므로, max_diff일 때의 총 시간이 limit보다 크면 어떤 level로도 해결할 수 없습니다. 따라서, if calc_time(max_diff) > limit: return -1 # 또는 문제에 따라 다른 처리? else: 이진 탐색을 통해 찾은 최소 level 반환 하지만 문제에서 "제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값"을 구하라고 했으므로, 제한 시간 내에 풀 수 없다면 명시하지 않았지만, 일반적으로는 -1을 반환하거나 에러를 반환할 수 있습니다. 문제의 매개변수 제한사항을 보지 못했으므로, 일단은 제한 시간 내에 풀 수 있는 입력만 주어진다고 가정하고 풀어보겠습니다. (만약 그렇지 않다면, 문제에서 어떻게 처리할지 명시해야 합니다.) 하지만 문제의 예시가 없으므로, 우리는 가정을 해야 합니다. 결론: 1. level의 범위: [min_level, max_level] min_level = min_possible = diff[0] (첫 번째 퍼즐을 풀기 위해) max_level = max(diffs) 2. calc_time(level) 함수 구현: total = times[0] # 첫 번째 퍼즐 for i in range(1, len(diffs)): if diffs[i] <= level: total += times[i] else: # 틀린 횟수 = diffs[i] - level total += (diffs[i] - level) * (times[i] + times[i-1]) + times[i] 3. 이진 탐색을 수행. 4. 만약 max_level일 때의 총 시간이 limit보다 크면, -1 반환? 문제에서 제한 시간 내에 풀 수 없는 경우에 대한 처리를 명시하지 않았으므로, 실제 문제에서는 어떻게 할지 확인이 필요합니다. 여기서는 일단 -1을 반환하도록 하겠습니다. 하지만, level을 max_level보다 더 높인다고 해도 총 시간은 변하지 않습니다. 따라서 max_level일 때 총 시간이 limit보다 크면, 어떤 level로도 해결할 수 없습니다. 구현: def solution(diffs, times, limit): n = len(diffs) if n == 0: return 0 # 퍼즐이 없으면 level은 0? 하지만 level은 양의 정수이므로 1? 하지만 퍼즐이 없으면 0도 가능? -> 문제에서 양의 정수라고 했지만, 퍼즐이 없으면 의미가 없으므로 0 반환? # 문제에서 퍼즐의 개수 n에 대한 언급이 없으므로, 빈 배열일 수 있습니다. # 첫 번째 퍼즐: 무조건 times[0]이 소요된다. # min_level = diffs[0] (첫 번째 퍼즐을 풀기 위해) max_level = max(diffs) # max_level일 때의 총 시간 계산 (모든 퍼즐이 한 번에 풀리는 경우) total_max = sum(times) if total_max > limit: return -1 # 제한 시간 내에 풀 수 없음 # min_level: diffs[0] (이것보다 작으면 첫 퍼즐을 못 품) low = diffs[0] high = max_level ans = max_level # 최소한 max_level은 만족하므로 while low <= high: mid = (low + high) // 2 t = calc_time(diffs, times, mid) if t <= limit: ans = mid high = mid - 1 else: low = mid + 1 return ans def calc_time(diffs, times, level): total = times[0] # 첫 번째 퍼즐 n = len(diffs) for i in range(1, n): if diffs[i] <= level: total += times[i] else: # 틀린 횟수 = diffs[i] - level total += (diffs[i] - level) * (times[i] + times[i-1]) + times[i] return total 그러나 이 코드는 첫 번째 퍼즐 이후의 퍼즐들만 고려하고, 첫 번째 퍼즐은 항상 times[0]을 사용합니다. 테스트 예시: 예시로 주어진 경우: diff=3, time_cur=2, time_prev=4, level=1 -> 14, level=2->8, level>=3->2 하지만 이 예시는 하나의 퍼즐에 대한 것이고, 두 번째 퍼즐이라고 가정해야 합니다. 따라서 diffs = [?, 3] 이고, times = [4,2] 라고 하면, 첫 번째 퍼즐: diff[0]=? (첫 번째 퍼즐의 난이도) -> 첫 번째 퍼즐은 4초가 걸리고, 두 번째 퍼즐: level=1 -> 3>1 -> (3-1)*(2+4)+2 = 2*6+2 = 14 level=2 -> 3>2 -> (3-2)*6+2 = 8 level=3 -> 3<=3 -> 2 따라서 총 시간: level=1: 4 + 14 = 18 level=2: 4+8=12 level=3: 4+2=6 만약 limit=10 이라면, level=2일 때 12>10 이므로 level=3이 최소 (6<=10) -> level=3 하지만 우리는 level의 최솟값을 구하는 것이므로, 첫 번째 퍼즐의 난이도가 첫 번째 퍼즐의 level 제약을 결정합니다. 여기서 첫 번째 퍼즐의 난이도가 무엇인지 모릅니다. 예시에서 첫 번째 퍼즐의 난이도는 주어지지 않았습니다. 따라서, 우리가 만든 함수는 첫 번째 퍼즐의 난이도가 diffs[0]으로 주어집니다. 예를 들어, 첫 번째 퍼즐의 난이도가 1이고, 두 번째 퍼즐의 난이도가 3, 첫 번째 퍼즐의 소요시간이 4, 두 번째가 2, limit=10 이라면, level은 최소 1 (첫 번째 퍼즐의 난이도 1 이상) 이어야 합니다. level=1: 총 시간 = 4 (첫 번째) + (3>1 -> (3-1)*(2+4)+2 = 14) -> 18 -> 18>10 -> 실패 level=2: 4 + (3>2 -> 8) = 12 -> 12>10 -> 실패 level=3: 4 + (3<=3 -> 2) = 6 -> 성공 -> 답 3 하지만 level=2일 때 첫 번째 퍼즐: diff[0]=1 <=2 -> 성공 (시간 4) 두 번째 퍼즐: diff[1]=3>2 -> 8 -> 총 12 level=3: 첫 번째 퍼즐: 1<=3 -> 4, 두 번째: 3<=3 -> 2 -> 총 6 따라서 level=3이 최소. 만약 첫 번째 퍼즐의 난이도가 3이라면? level은 최소 3이어야 합니다. level=3: 첫 번째 퍼즐: 3<=3 -> 4, 두 번째: 3<=3 -> 2 -> 총 6 -> 성공 -> 답 3 첫 번째 퍼즐의 난이도가 2라면? level은 최소 2. level=2: 첫 번째: 2<=2 -> 4, 두 번째: 3>2 -> 8 -> 총 12 -> limit=10이면 실패 level=3: 성공 -> 답 3 따라서 첫 번째 퍼즐의 난이도가 2인 경우, level=2로는 12가 되어 실패하고 level=3이 필요. 이제, 우리의 이진 탐색은 첫 번째 퍼즐의 난이도가 2인 경우: low = 2, high = max(diffs)=3 mid = (2+3)//2 = 2 -> t = calc_time(2) = 4 + (3>2 -> 8) = 12 > limit(10) -> low = 3 mid=3 -> t=6 <=10 -> ans=3, high=2 -> 종료. 따라서 3 반환. 또 다른 예시: diffs = [1, 2, 3, 4], times = [1,1,1,1], limit=10 첫 번째 퍼즐: 1 -> 시간 1 두 번째: level이 2이상이면? diff[1]=2: level>=2 -> 1 level<2 (level=1) -> (2-1)*(1+1)+1 = 2+1=3 세 번째: diff[2]=3 level>=3 -> 1 level=2 -> (3-2)*(1+1)+1 = 2+1=3 level=1 -> (3-1)*(1+1)+1 = 4+1=5 네 번째: diff[3]=4 level>=4 -> 1 level=3 -> (4-3)*(1+1)+1=2+1=3 level=2 -> (4-2)*(1+1)+1=4+1=5 level=1 -> (4-1)*(1+1)+1=6+1=7 총 시간: level=4: 1+1+1+1=4 level=3: 첫 퍼즐: level=3>=1 -> 1, 두 번째: 2<=3 -> 1, 세 번째: 3<=3 -> 1, 네 번째: 4>3 -> (4-3)*(1+1)+1=3 -> 총 1+1+1+3=6 level=2: 첫 퍼즐: 1<=2 -> 1 두 번째: 2<=2 -> 1 세 번째: 3>2 -> (3-2)*2+1=3 네 번째: 4>2 -> (4-2)*2+1=5 -> 총 1+1+3+5=10 level=1: 첫 퍼즐: 1<=1 -> 1 두 번째: 2>1 -> (2-1)*2+1=3 세 번째: 3>1 -> (3-1)*2+1=5 네 번째: 4>1 -> (4-1)*2+1=7 -> 총 1+3+5+7=16 따라서 limit=10일 때, level=2이면 10으로 통과 -> 최소 level=2 우리의 이진 탐색: min_level = diffs[0]=1 max_level = max(diffs)=4 calc_time(1)=16>10 -> 실패 calc_time(2)=10<=10 -> 성공 -> ans=2, 그리고 더 작은 level이 있는지 확인: low=1, high=4 -> mid=2 -> 성공 -> high=1 -> 이제 low=1, high=1 -> mid=1 -> 16>10 -> 실패 -> low=2 -> 종료. 따라서 2 반환. 그러나 level=2가 최소이므로 맞습니다. 하지만 level=0? -> 첫 번째 퍼즐의 난이도가 1이므로 level=0이면 첫 퍼즐을 풀 수 없습니다. 따라서 level은 1부터 시작해야 하지만, min_level을 첫 퍼즐의 난이도로 설정했으므로 1입니다. 주의: 첫 번째 퍼즐의 난이도가 1이므로, level=1이면 첫 퍼즐은 풀 수 있습니다. 따라서 이진 탐색의 범위는 [diffs[0], max(diffs)] 입니다. 그러나 만약 모든 퍼즐의 난이도가 0인 경우? -> 문제에서 양의 정수라고 했으므로, 최소 1입니다. 구현 시 주의: n=1인 경우 (퍼즐이 하나) 첫 번째 퍼즐만 있음 -> 이전 퍼즐이 없으므로, if diffs[0] <= level: 시간 = times[0] else: # 틀린 횟수 = diffs[0] - level # 하지만 이전 퍼즐이 없으므로, time_prev=0으로 처리? # 문제에서 첫 번째 퍼즐은 이전 퍼즐이 없으므로, 틀렸을 때 이전 퍼즐을 다시 풀지 않습니다. # 따라서 첫 번째 퍼즐은 틀리면 안 된다고 해석? # 우리의 가정: 첫 번째 퍼즐은 무조건 한 번에 풀린다. -> times[0] 만 사용. 따라서 n=1인 경우: level >= diffs[0] 이어야 하고, 총 시간 = times[0] 따라서 calc_time 함수는 n=1인 경우를 자연스럽게 처리합니다. 코드 구현: def calc_time(diffs, times, level): total = times[0] # 첫 번째 퍼즐 n = len(diffs) for i in range(1, n): if diffs[i] <= level: total += times[i] else: total += (diffs[i] - level) * (times[i] + times[i-1]) + times[i] return total 이제 solution 함수에서: if n==0: return 0 # 퍼즐이 없으면 0 max_level = max(diffs) # max_level일 때의 총 시간 계산 total_max = calc_time(diffs, times, max_level) # 이 때는 모든 퍼즐이 한 번에 풀리므로, sum(times)와 같을까? # n>=2인 경우, 두 번째 퍼즐부터는 모두 diffs[i] <= max_level 이므로 times[i]를 더함 -> 따라서 sum(times)와 같다. # n=1인 경우: times[0] -> sum(times)와 같다. if total_max > limit: return -1 low = diffs[0] # 첫 번째 퍼즐의 난이도 high = max_level ans = max_level # 일단 max_level은 가능 while low <= high: mid = (low+high)//2 t = calc_time(diffs, times, mid) if t <= limit: ans = mid high = mid - 1 else: low = mid + 1 return ans 테스트: n=1, diffs=[5], times=[10], limit=10 min_level = 5 max_level = 5 total_max = 10 <= limit -> 이진 탐색: low=5, high=5 -> mid=5 -> t=10<=10 -> ans=5 -> return 5 만약 limit=9라면? total_max=10>9 -> return -1 또 다른 테스트: n=1, diffs=[5], times=[10], limit=10 -> 5 n=1, diffs=[5], times=[10], limit=15 -> 5 n=1, diffs=[3], times=[10], limit=10 -> 3 n=2: diffs=[1,5], times=[1,10], limit=? level의 범위: [1,5] level=5: 총 시간 = 1 + 10 = 11 level=4: 두 번째 퍼즐: 5>4 -> (5-4)*(10+1)+10 = 1*11+10 = 21 -> 총 1+21=22 level=3: 5>3 -> (5-3)*11+10 = 22+10=32 -> 총 33 level=2: (5-2)*11+10 = 33+10=43 -> 44 level=1: (5-1)*11+10 = 44+10=54 -> 55 따라서 level=5일 때 11, level=4일 때 22, ... limit=11: level=5 -> 11<=11 -> 성공 -> 최소 level=5 limit=10: level=5 -> 11>10 -> 실패 -> -1 반환? 하지만 level=5일 때 11>10 이므로, level 5로도 10초 내에 풀 수 없고, level을 5보다 높여도 총 시간은 11로 동일 -> 따라서 -1 그러나 level=5일 때 두 번째 퍼즐: 5<=5 -> 10초만 소요 -> 총 1+10=11? 맞습니다. 따라서 limit=10이면 11>10 -> 실패. 하지만 level=5일 때 두 번째 퍼즐을 푸는 시간이 10초인데, 첫 번째 퍼즐 1초를 합하면 11초입니다. 따라서 -1 반환. 그러나 문제에서 제한 시간 내에 풀 수 없는 경우에 대한 반환을 어떻게 할지 명시되지 않았으므로, 문제가 요구하는 대로 -1을 반환합니다. 이제 코드를 작성합니다. 주의: 이진 탐색에서 항상 해를 찾을 수 있도록, max_level일 때 total_max <= limit 이면 해가 존재하고, 아니면 -1을 반환합니다. 따라서: total_max = calc_time(diffs, times, max_level) if total_max > limit: return -1 ... 이진 탐색 ... 이진 탐색은 항상 [diffs[0], max_level] 사이의 해를 찾습니다. 하지만 이진 탐색에서 low가 diffs[0]이고, 이 범위 내에서 조건을 만족하는 가장 작은 level을 찾습니다. 이 코드를 제출합니다. 그러나 문제에서 첫 번째 퍼즐에 대한 처리에 대한 명확한 해석이 없어서 우리의 가정에 따랐습니다. 만약 문제의 의도가 첫 번째 퍼즐도 틀렸을 때 이전 퍼즐이 없으므로, 첫 번째 퍼즐을 틀리면 이전 퍼즐을 다시 풀 수 없어서 게임이 진행되지 않는다고 본다면, 첫 번째 퍼즐은 무조건 맞춰야 하므로 level>=diffs[0]이어야 한다는 가정은 맞습니다. 따라서 이대로 구현합니다. 하지만, 첫 번째 퍼즐을 틀릴 수는 없지만, 두 번째 퍼즐을 풀 때 첫 번째 퍼즐을 다시 풀 수 있으므로, 첫 번째 퍼즐은 틀리지 않아도 됩니다. (이미 맞춘 첫 번째 퍼즐을 다시 풀기만 하면 됨) 그러나 첫 번째 퍼즐을 풀 때는 틀리면 안 됩니다. 첫 번째 퍼즐을 풀 때 틀리면, 이전 퍼즐이 없기 때문에 다시 풀 수 없으므로 게임이 진행되지 않습니다. 따라서 첫 번째 퍼즐은 반드시 한 번에 맞춰야 합니다. 이 가정은 변함없습니다. 코드 작성:</think>### 문제 해결 방법 주어진 퍼즐 게임에서 제한 시간 내에 모든 퍼즐을 해결하기 위한 최소 숙련도(level)를 찾는 문제입니다. 핵심은 다음과 같습니다: 1. **첫 번째 퍼즐**: 이전 퍼즐이 없으므로 반드시 `diff[0] ≤ level`이어야 합니다. 소요 시간은 `times[0]`입니다. 2. **이후 퍼즐**(i ≥ 1): - `diff[i] ≤ level`: 한 번에 풀리며, 소요 시간은 `times[i]`입니다. - `diff[i] > level`: `(diff[i] - level)`번 틀리고, 각 틀릴 때마다 `(times[i] + times[i-1])` 시간이 소요되며, 마지막에 `times[i]` 시간이 추가됩니다. 총 시간은 `(diff[i] - level) × (times[i] + times[i-1]) + times[i]`입니다. ### 해결 전략 1. **이진 탐색**으로 최소 level 탐색: - **하한(low)**: 첫 번째 퍼즐의 난이도 `diffs[0]` (이보다 작으면 첫 퍼즐 풀 수 없음). - **상한(high)**: 모든 퍼즐의 최대 난이도 `max(diffs)` (이 값이면 모든 퍼즐 한 번에 풀림). 2. **시간 계산 함수**: 주어진 level로 모든 퍼즐을 풀 때의 총 시간을 계산합니다. 3. **예외 처리**: `max(diffs)` level에서도 제한 시간을 초과하면 풀 수 없으므로 `-1` 반환. ### 코드 구현 ```python def solution(diffs, times, limit): n = len(diffs) if n == 0: return 0 # 퍼즐이 없는 경우 max_level = max(diffs) # max_level일 때 총 시간 계산 (모든 퍼즐 한 번에 풀림) total_max = times[0] for i in range(1, n): total_max += times[i] # max_level로도 제한 시간 초과 시 -1 반환 if total_max > limit: return -1 # 이진 탐색 low = diffs[0] high = max_level ans = max_level while low <= high: mid = (low + high) // 2 total_time = times[0] # 첫 번째 퍼즐 시간 for i in range(1, n): if diffs[i] <= mid: total_time += times[i] else: # 틀린 횟수 = (diff[i] - mid) total_time += (diffs[i] - mid) * (times[i] + times[i-1]) + times[i] if total_time <= limit: ans = mid high = mid - 1 # 더 작은 level 탐색 else: low = mid + 1 return ans ``` ### 예제 설명 **입력**: `diffs = [1, 5]`, `times = [1, 10]`, `limit = 11` - **level = 5**: - 첫 퍼즐: `1 ≤ 5` → 시간 1 - 두 번째 퍼즐: `5 ≤ 5` → 시간 10 총 시간 = 1 + 10 = 11 (limit 만족 → 최소 level 5) - **level = 4**: - 두 번째 퍼즐: `5 > 4` → `(5-4)×(10+1) + 10 = 21` 총 시간 = 1 + 21 = 22 (limit 초과) **출력**: `5`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值