알고스팟에 등록되어 있는 문제가 아닌데 질문을 해도 되는지 모르겠네요..혹시나 친절한 분의 도움을 받을 수 있을까 해서 민망한 소스코드 올리고 질문드립니다..^^;;
이번 코드잼 1라운드 문제였습니다.
에너지 최대치가 정해져 있고, activity들을 수행할때 소비되는 에너지와 수행후 보상되는 에너지들이 주어질 때, 각 (activity들의 가치) * (사용하는 에너지) 의 총합의 최대값을 구하는 문제입니다.
저는 이것을 분할정복법으로 풀어보려고 했는데, small input에 대해서는 올바른 output이 나오는데, large input에 대해서는 몇몇 케이스가 정답보다 작은 값이 나옵니다.
small input에서 오답이 나와야 뭔가 계산이라도 해보면서 오류를 찾아볼텐데, large input에서 오답이 나오니까 볼 엄두도 안나네요..
종만님의 solution을 보고 훨씬 쉬운 해결방법에 대해서도 배웠고 이해도 했으나, 제가 풀던 방법에서도 문제가 무엇이었는지를 알아야 동일한 실수를 하지 않을것 같아서 질문 드립니다.
이 알고리즘의 오류는 뭘까요?
importjava.util.Scanner;/** * CodeJam 2013 Round 1A * Problem B. Manage your Energy */publicclassB_qna{privateintE,R,N;privateint[]v;privatevoidgoodluck()throwsException{// ready variablesintnumberOfCases;// get fileScannersc=newScanner(System.in);numberOfCases=sc.nextInt();// make outputfor(intcasenum=0;casenum<numberOfCases;casenum++){E=sc.nextInt();R=sc.nextInt();N=sc.nextInt();v=newint[N];for(inti=0;i<N;i++)v[i]=sc.nextInt();Stringresult=""+solve(0,N-1,E,Math.min(R,E));System.out.println("Case #"+(casenum+1)+": "+result);}}/** * 분할정복방식을 사용하여 각 (energe)*(activity value) 총합의 최대값을 구한다. * 주어진 구간에서 최대값을 구하여 Vprev, Vmax, Vnext 로 구간을 분할하여 Vmax에 최선을 다한다. * Vmax에 최대한 E에 가까운 에너지를 사용할 수 있도록 Vprev에서는 가능한 최대의 에너지를 남겨준다. * * @param sidx v[]에 대한 start index * @param eidx v[]에 대한 end index * @param se start energy 구간 시작시 사용가능 에너지 * @param ee end energy 구간이 끝날때 남아있어야 하는 에너지 * @return (energe)*(activity value) 총합의 최대값 */privatelongsolve(intsidx,inteidx,intse,intee){if(sidx==eidx){intue=se-ee+R;if(ue<0)ue=0;if(ue>E)ue=E;returnue*(long)v[sidx];}intvmaxIdx=0;intvmax=Integer.MIN_VALUE;for(inti=sidx;i<=eidx;i++)if(v[i]>vmax){vmax=v[i];vmaxIdx=i;}longresult=0;intmaxRecover,needRecover;// Vprev 에 대해 계산intnexte=se;if(vmaxIdx-1>=sidx){maxRecover=R*(vmaxIdx-sidx);if(maxRecover<0)maxRecover=0;if(maxRecover>E)maxRecover=E;needRecover=E-se;if(needRecover<0)needRecover=0;if(needRecover>E)needRecover=E;if(maxRecover>=needRecover)nexte=E;elsenexte=E-(needRecover-maxRecover);result+=solve(sidx,vmaxIdx-1,se,nexte);}// Vmax 에 대해 계산maxRecover=0;if(vmaxIdx+1<=eidx){maxRecover=R*(eidx-vmaxIdx);if(maxRecover<0)maxRecover=0;}intue=nexte+R+maxRecover-ee;if(ue<0)ue=0;if(ue>nexte)ue=nexte;result+=ue*(long)v[vmaxIdx];// Vnext 에 대해 계산if(vmaxIdx+1<=eidx){result+=solve(vmaxIdx+1,eidx,Math.min(nexte-ue+R,E),ee);}returnresult;}publicstaticvoidmain(String[]args){try{newB_qna().goodluck();}catch(Exceptione){e.printStackTrace();}}}
teuskim3
알고스팟에 등록되어 있는 문제가 아닌데 질문을 해도 되는지 모르겠네요..혹시나 친절한 분의 도움을 받을 수 있을까 해서 민망한 소스코드 올리고 질문드립니다..^^;;
이번 코드잼 1라운드 문제였습니다.
에너지 최대치가 정해져 있고, activity들을 수행할때 소비되는 에너지와 수행후 보상되는 에너지들이 주어질 때, 각 (activity들의 가치) * (사용하는 에너지) 의 총합의 최대값을 구하는 문제입니다.
저는 이것을 분할정복법으로 풀어보려고 했는데, small input에 대해서는 올바른 output이 나오는데, large input에 대해서는 몇몇 케이스가 정답보다 작은 값이 나옵니다.
small input에서 오답이 나와야 뭔가 계산이라도 해보면서 오류를 찾아볼텐데, large input에서 오답이 나오니까 볼 엄두도 안나네요..
종만님의 solution을 보고 훨씬 쉬운 해결방법에 대해서도 배웠고 이해도 했으나, 제가 풀던 방법에서도 문제가 무엇이었는지를 알아야 동일한 실수를 하지 않을것 같아서 질문 드립니다.
이 알고리즘의 오류는 뭘까요?
11년 전