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 --

返信してくれてありがとう、次のpythonスクリプトによって生成された入力でコードを実行しました-

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 ミリ秒に短縮する必要があります。rfeak によって提案されているように、HashMaps と HashSets を置き換える試みに取り組んでおり、このシナリオでメモ化が役立つかどうかも疑問に思っています。お知らせ下さい。

EDIT2 - 配列を使用してアルゴを再コーディングするとうまくいったようです。ただし、同じコードを別の時間に再送信すると、受け入れられたソリューションと時間制限を超えました:DI は、ハッシュマップを使用してもう少し最適化する別の方法を持っています。助けてくれてありがとう!

4

1 に答える 1

7

ローカルで実行する場合、プログラムはどのくらいのメモリを使用しますか?

十分なメモリがない状態で Java プログラムを実行している場合、ガベージ コレクションに多くの時間を費やしている可能性があります。これはあなたの 1 秒の時間を破壊する可能性があります。

時間とメモリを節約する必要がある場合 (未定)、2 つの提案があります。

に置き換えHashSet<Integer>ますBitSet。同様のインターフェイス、より高速な実装、および使用メモリの大幅な削減。特に、問題に表示される数字については。

に置き換えますMap<Integer,X>-X[]整数キーは、単に配列への int (プリミティブ) インデックスにすることができます。繰り返しますが、より速く、より小さく。

于 2011-02-04T23:30:10.063 に答える