2011-02-04 3 views
6

임 문제를 코딩 (참조 --http : //www.codechef.com/FEB11/problems/THREECLR/)를 초과 아래자바 문제가 시간 제한 문제

을 내 코드는

import java.io.*; 
import java.util.*; 


public class Main { 

static String ReadLn (int maxLg) // utility function to read from stdin 
    { 
     byte lin[] = new byte [maxLg]; 
     int lg = 0, car = -1; 
     String line = ""; 

     try 
     { 
      while (lg < maxLg) 
      { 
       car = System.in.read(); 
       if ((car < 0) || (car == '\n')) break; 
       lin [lg++] += car; 
      } 
     } 
     catch (IOException e) 
     { 
      return (null); 
     } 

     if ((car < 0) && (lg == 0)) return (null); // eof 
     return (new String (lin, 0, lg)); 
    } 

public static boolean iscontains(HashMap<Integer,HashSet<Integer>> resultmap,HashSet<Integer> b, int index) 
{ 
    boolean result=false; 
    for(Iterator<Integer> iter = b.iterator();iter.hasNext();) 
     { int tmp=Integer.valueOf(iter.next().toString()); 
      if(resultmap.get(index).contains(tmp)) 
        result=true;     
     } 

    return result; 
} 


public static void main(String[] args) throws InterruptedException, FileNotFoundException { 
    try { 

    HashMap<Integer,HashSet<Integer>> pairlist = new HashMap<Integer,HashSet<Integer>>(); 
    String input=null; 
    StringTokenizer idata; 
    int tc=0; 
    input=Main.ReadLn(255); 
    tc=Integer.parseInt(input); 
    while(--tc>=0) 
    { 
     input=Main.ReadLn(255); 
     idata = new StringTokenizer (input);idata = new StringTokenizer (input); 
     int dishnum= Integer.parseInt(idata.nextToken()); 
     int pairnum= Integer.parseInt(idata.nextToken()); 
     while (--pairnum>=0) 
     { 
      input=Main.ReadLn(255); 
      idata = new StringTokenizer (input);idata = new StringTokenizer (input); 
      int dish1=Integer.parseInt(idata.nextToken()); 
      int dish2=Integer.parseInt(idata.nextToken()); 
      if(pairlist.containsKey((Integer)dish1)) 
      { 
       HashSet<Integer> dishes=new HashSet<Integer>(); 
       dishes=pairlist.get(dish1); 
       dishes.add(dish2); 
       pairlist.put(dish1, dishes); 
      } 
      else 
      { 
       HashSet<Integer> dishes=new HashSet<Integer>(); 
       dishes.add(dish2); 
       pairlist.put(dish1, dishes); 
      } 
     } 
     int maxrounds=1; 
     HashMap<Integer,HashSet<Integer>> resultlist = new HashMap<Integer,HashSet<Integer>>(); 
     HashSet<Integer> addresult=new HashSet<Integer>(); 
     addresult.add(1); 
     resultlist.put(1,addresult); 
     System.out.print("1"); 
     for(int i=2;i<=dishnum;i++) 
     { 
      boolean found_one=false; 
      boolean second_check=false; 
      int minroundnum=maxrounds; 
      boolean pairlistcontains=false; 
      pairlistcontains=pairlist.containsKey(i); 
      for(int j=maxrounds;j>=1;j--) 
      { 
       if(!found_one){ 
       if(pairlistcontains) 
       { 
        if(!iscontains(resultlist,pairlist.get((Integer) i),j)) 
        { 
         for(Iterator<Integer> resultiter = resultlist.get(j).iterator();resultiter.hasNext();) 
         { 
          if(pairlist.get(resultiter.next()).contains(i)) 
           second_check=true; 
         } 
         if(second_check==false) 
         { 
          found_one=true; 
          minroundnum=j; 
          j=0; 
          //second_check=false; 
         } 
        } 

       } 
       else 
       { 
        for(Iterator<Integer> resultiter = resultlist.get(j).iterator();resultiter.hasNext();) 
        { 
         if(pairlist.get(resultiter.next()).contains(i)) 
          second_check=true; 
        } 
        if(second_check==false) 
        { 
         found_one=true; 
         minroundnum=j; 
         j=0; 
         //second_check=false; 
        } 

       } 
       second_check=false; 


      } 
     } 
      if((minroundnum==maxrounds)&&(found_one==false)) 
       { 
       ++minroundnum; 
       ++maxrounds; 
       } 
      else 
      { 
       found_one=false; 
      } 
      HashSet<Integer> add2list=new HashSet<Integer>(); 
      if(resultlist.containsKey(minroundnum)) 
      { 
       add2list=resultlist.get(minroundnum); 
       add2list.add(i); 
      } 
      else 
      { 
       add2list.add(i); 
      } 
      resultlist.put(minroundnum,add2list); 
      System.out.print(" "); 
      System.out.print(minroundnum); 


     } 
     if((tc !=-1)) 
      System.out.println(); 

    } 


    } 
    catch(Exception e){System.out.println(e.toString());} 
}} 

Ideone과 같은 온라인 심사 위원에서이 코드를 확인하고 원하는 결과를 얻었습니다. 하지만이 코드를 제출하면 시간 제한 초과 오류가 발생합니다. 필자는 Ideone에이 코드를 충분히 큰 입력 집합으로 테스트했으며 실행에 걸린 시간은 1 초 미만이었다. 그것은 내 인생에서 모든 행복을 흘린 것처럼 보이는 버그 나 메모리 누수가있는 것 같습니다. 모든 도움말/팁을 크게 높이세요.

감사

EDIT1은 -

, 나는 다음과 같은 파이썬 스크립트에 의해 생성 된 입력 코드를 실행 한 대답들에 대한

감사 -

import random 
filename="input.txt" 
file=open(filename,'w') 
file.write("50") 
file.write("\n") 
for i in range(0,50): 
     file.write("500 10000") 
     file.write("\n") 
     for j in range(0,10000): 
       file.write(str(random.randrange(1,501))+" "+str(random.randrange(1,501))) 
       file.write("\n") 
file.close() 

그리고 내 코드는 무려했다 위의 스크립트에서 제공 한 입력에서 실행하려면 71052 밀리 초. 이제 실행 시간을 8000 밀리 초로 줄여야합니다. Im는 rfeak가 제안한대로 HashMaps와 HashSet을 대체하려고 노력하고 있으며,이 시나리오에서는 메모 작성이 도움이되는지 궁금합니다. 제발 조언.

EDIT2 - 어레이를 사용하여 내 고문을 재 코딩 한 것 같습니다. 단지 다른 시간에 동일한 코드를 다시 제출하면 Accepted Solution과 Time Limit가 초과됩니다. D 조금 더 최적화하기 위해 해시 맵을 사용하는 다른 방법이 있습니다. 도움 주셔서 감사합니다.

+3

당신은 훨씬 더 큰 입력을 먹고 있으며 코드가 처리하는 데 너무 오래 걸리는 것으로 생각 해본 적이 있습니까? –

+0

그들이 제출하는 데이터 세트의 크기가 얼마나되는지 알고 계십니까? 그 데이터 세트를 얻을 수 있습니까? –

+0

내 추측으로는 발생하지 않는 입력을 기대하고 있거나 프로그램이 무한 루프에 빠지게하는 입력이 있다고 생각합니다. –

답변

7

로컬에서 실행할 때 프로그램에서 사용하는 메모리 용량은 어느 정도입니까?

메모리가 부족하여 Java 프로그램을 실행하는 경우 가비지 수집을 위해 많은 시간을 소비 할 수 있습니다. 이것은 당신의 1 초 시간을 파괴 할 수 있습니다.

시간과 메모리를 절약해야하는 경우 (결정할 ...), 나는 2 개의 suggetions을 가지고 있습니다.

BitSet으로 바꿉니다. 비슷한 인터페이스, 훨씬 빠른 구현, 훨씬 적은 메모리 사용. 특히 문제에서 볼 수있는 숫자와 함께.

Map<Integer,X>X[]으로 바꾸십시오. 정수 키는 단순히 배열의 int (원시) 색인 일 수 있습니다. 다시 말하지만, 더 빠르고 작습니다.

+0

확실히'HashSet'과'Map'을 제거하십시오. 문제에서 주어진 숫자는 배열을 위해 충분히 작습니다 (또는'BitSet'은 그보다 더 빠를 수도 있습니다 만, 당신이 여기 필요하다고 생각하지 않습니다). – IVlad

+0

제안 해 주셔서 감사합니다. BitSet 구현에 대해서는 명확하지 않습니다. JavaDoc은 숫자의 비트 표현을 포함하고 있으며 논리 연산을 지원한다고 말합니다. 주로 입력 데이터에 대한 그런 조작을하고 싶지는 않지만 가장 실용적이고 최상의 접근 방법이라면 분명히 시도해 볼 것입니다. 제발 조언. – Jcoder

+0

@JCoder - 내부 표현을 설명하는 방법을 무시하십시오. BitSet을 int (프리미티브) 세트로 생각하는 것이 가장 좋습니다. 세트는 정수를 포함하거나 포함하지 않습니다. 그 경우는, BitSet.get (someInt)를 호출합니다. 집합에 정수를 넣으려면 BitSet.set (someInt)을 호출합니다. 이 방법으로 정확히 으로 동작합니다. ... 이제 Set 보다 작은 이유에 대해 정말로 관심이 있으시면 저의 답변에 추가 할 수 있습니다. – rfeak