백준

백준 17845 수강 과목

콩순이냉장고 2023. 12. 12. 23:08

문제 URL : https://www.acmicpc.net/problem/17845

 

17845번: 수강 과목

첫줄에 서윤이의 최대 공부시간 N (1 ≤ N ≤ 10,000), 과목 수 K (1 ≤ K ≤ 1,000)이 공백을 사이에 두고 주어진다.  이후 K개의 줄에 중요도 I (1 ≤ I ≤ 100,000), 필요한 공부시간 (1 ≤ T ≤ 10,000)이

www.acmicpc.net

 

문제 접근법:

배낭문제이지만 dfs+메모이제이션으로 활용해서 풀수있는문제입니다.

메모리는 10000*1000 이라 1천만까지는 괜찮기때문에 

 

메모이제이션이 c++에선 가능하지만

똑같이 코딩했는데 python에서 시간초과가 나더군요 

파이썬은 dfs + 메모이제이션이 힘든것같습니다.

 

처음에 파이썬으로 풀어서 시간초과 나길래 어딜 개선해야되나 싶었는데 찾질못해서 그냥 c++로 풀었더니

c++은 되고 파이썬은 안되고 참 의아했습니다.

 

소스코드:

#include <bits/stdc++.h>
using namespace std;
int n,k;
int dp[10001][1001];
vector<pair<int,int>> v;
void input(){
	cin>>n>>k;
	int a,b;
	for(int i=0;i<k;i++){
		cin>>a>>b;
		v.push_back({a,b});
	}
}
int dfs(int sum=n,int cur=0){
	if(cur>=k)return 0;
	int &cache = dp[sum][cur];
	if(cache!=-1)return cache;
	if(sum>=v[cur].second)
		cache = max(cache,dfs(sum-v[cur].second,cur+1)+v[cur].first);
	return cache = max(cache,dfs(sum,cur+1));
}
void solve(){
	memset(dp,-1,sizeof(dp));
	cout<<dfs()<<"\n";	
}
int main ()
{	
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//freopen("input.txt","r",stdin);
	input();
	solve();
}

 

파이썬 시간초과코드

import sys
sys.setrecursionlimit(2000000)
input = sys.stdin.readline
n,k = map(int,input().rstrip().rsplit())
l = [list(map(int,input().rstrip().rsplit())) for i in range(k)]
dp = [[-1 for i in range(k)] for j in range(n+1)]
def dfs(time, cur):
    global k,l,dp
    if time <= 0 or cur>=k :return 0
    if dp[time][cur] != -1 :return dp[time][cur]

    if time>= l[cur][1]:
        dp[time][cur] = max(dp[time][cur],dfs(time-l[cur][1],cur+1)+l[cur][0])
    dp[time][cur] = max(dp[time][cur],dfs(time,cur+1))
    return dp[time][cur]
print(dfs(n,0))

두코드 차이가 없을정도로 똑같은데?

컴파일언어가 인터프리터 보다는 빠르다는 것은 알고있었지만

알고리즘 문제를 풀다보면 그렇게 차이가 안나는 것처럼 보였는데

여기서 그차이를 느끼게 되네요

 

궁금한점 혹은 모르는점 논리적인 오류등 어떤질문이든 댓글은 언제나 환영입니다.