2

私は ACM でこの問題に対するプログラムを提出してきました。問題 ID=1922しかし、私のソリューションはテスト 3 で時間制限を超え続けます。

私の考えは、ブルートフォースを使用することですが、いくつかの枝を切り落とすことです。以下は私のJavaコードです。より速い解決策や改善があれば幸いです...難易度は195しかないので、これはまったく難しくないと思いますが、受け入れられません。

やっと受理されました。アルゴリズムは、最初にヒーローをソートし、最初に最小の願いから始めます。ちょうど)..

私の Java コードは、これまでのところ最速のソリューション ランクです

どうもありがとう!

public class testtest
{
    static boolean[] used;
    // length of heros
    static int ulen;
    // list of heros
    static Wish[] w;
    // number of possible teams
    static int count = 0;
    // and output
    static StringBuilder str = new StringBuilder();

    // add the team

    // check if it is a valid team
    static boolean check(int len)
    {
        for (int i = 0; i < ulen; i ++)
        {
            if (!used[i])
            {
                            // adding another hero makes it reliable, so invalid
                if (w[i].wish <= len + 1)
                {
                    return false;
                }
            }

        }
        return true;
    }

    // search the teams, team size = total, current pick = len, start from root + 1
    static void search(int root, int total, int len)
    {
        if (len >= total) // finish picking len heros
        {
            if (check(total))  // valid
            {
                print(total);  // add to output
            }
            return;
        }
        for (int i = root + 1; i < ulen; i ++)
        {
            if (w[i].wish > len + ulen - i)
            {
                return; // no enough heros left, so return
            }
            else
            if (w[i].wish <= total)  // valid hero for this team
            {
                used[i] = true;
                search(i, total, len + 1);  // search next hero
                used[i] = false;
            }
        }
    }

    public static void main(String[] args) throws IOException
    {
        BufferedReader rr = new BufferedReader(new InputStreamReader(System.in));
        ulen = Integer.parseInt(rr.readLine());
        w = new Wish[ulen];
        for (int i = 0; i < ulen; i ++)
        {
            w[i] = new Wish(i + 1, Integer.parseInt(rr.readLine()));
        }
        Arrays.sort(w);
        used = new boolean[ulen];
        Arrays.fill(used, false);
        for (int i = 1; i <= ulen; i ++)
        {
            for (int j = 0; j <= ulen - i; j ++)
            {
                if (w[j].wish <= i) // this hero is valid
                {
                    used[j] = true;
                    search(j, i, 1);
                    used[j] = false;
                }
            }
        }
        System.out.println(count);
        System.out.print(str);
    }
}
4

2 に答える 2

1

これは、サンプル テストで ~0.00013 秒 (私の CPU 上) で実行されるものです。

import java.io.*; 
import java.util.List;
import java.util.ArrayList; 
import java.util.Map;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Arrays;

/**
 * Hero.java
 *
 * This program solves the Super Hero problem put forth by Timus Online Judge  
 * http://acm.timus.ru/problem.aspx?space=1&num=1922
 *
 * @author  Hunter McMillen
 * @version 1.0 12/29/2012
 */
public class Hero {
    private static Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
    private static List<Integer>                indices  = new ArrayList<Integer>();
    private static boolean[]                    used;

    /**
     * Entry point into the application
     *
     * @args command line arguments
     */ 
    public static void main(String[] args) throws IOException {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    int numHeroes, wish;
    List<Integer> heroes = new ArrayList<Integer>();
    List<List<Integer>> groups;

    // read number of heroes 
    numHeroes = Integer.parseInt(in.readLine());

    // read 'numHeroes' wishes from stdin
    // filter out heroes that have a minimum required that exceeds
    // the number of heroes
    for(int i = 0; i < numHeroes; i++) {
        wish = Integer.parseInt(in.readLine());
        if(wish <= numHeroes)
        heroes.add(wish);
    }

    // split into groups
    groups = reliableGroups(heroes);

    // output results
    System.out.println(groups.size());
    for(List<Integer> g : groups) {
        System.out.println(g.size() + " " + g.toString().replaceAll("[\\]\\[\\,]", ""));
    }
    }

    /**
     * Determines whether a group is effective, meaning that all wishes
     * for that group are met
     *
     * @group The group to evaluate for effectiveness
     */
    public static boolean isEffective(List<Integer> group)  {
    int maxWish = Integer.MIN_VALUE;
    int temp; 

    // find the maximum wish size of all members in group
    for(int i = 0; i < group.size(); i++) {
        if((temp = indexMap.get(group.get(i))) > maxWish)
        maxWish = temp;
    }

    // make sure that the maximum wish size is respected
    return group.size() >= maxWish;
    }

    /**
     * Checks to see if there exists some other superhero
     * that when added to this group makes another effective group
     *
     * @effectiveGroup The current grouping that is effective but might
     *                 not be reliable
     */ 
    public static boolean isReliable(List<Integer> effectiveGroup) {
    for(int i = 1; i <= indices.size(); i++) {
        if(!used[i]) {
        // add another hero to this group to see if it remains effective 
        effectiveGroup.add(i);

        // if it is still effective, then this group is not reliable
        if(isEffective(effectiveGroup))
            return false;

        // remove the hero that was temporarily added
        effectiveGroup.remove(effectiveGroup.size()-1);
        }
    }

    // true if adding any unused member to this group made it ineffective
    return true;
    }

    /**
     * Separates the List<Integer> of heroes into reliable groups
     *
     * @heroes The List of heroes
     */
    public static List<List<Integer>> reliableGroups(List<Integer> heroes) {
    List<List<Integer>> groups = new ArrayList<List<Integer>>();
    boolean       effective    = true;
    int h, current;

    // create HashMap with mapping between hero wish values and their index
    for(int i = 1; i <= heroes.size(); i++) {
        indices.add(i);
        indexMap.put(i, heroes.get(i-1));
    }

    // create an array to track which heroes have been used
    used = new boolean[indices.size()+1];
    Arrays.fill(used, false);

    List<int[]>   combinations;
    List<Integer> tempList;
    for(int i = 1; i <= indices.size(); i++) { 
        h = indexMap.get(i);

        combinations = combination(heroes, h);

        // iterate over all combinations making sure the wish values are below
        // the threshold for this hero at map index `i`
        for(int[] aCombination : combinations) {
        for(int j = 0; j < aCombination.length; j++) {
            current = aCombination[j];
            used[current] = true;
            if(indexMap.get(current) > h) {
            effective = false;
            break;
            }
        }

        // create a List from the integer[] combination
        tempList = asList(aCombination);

        // if the group makeup is reliable, save it
        if(effective && !groups.contains(tempList) && isReliable(tempList))
            groups.add(new ArrayList<Integer>(tempList));

        // reset flags
        effective = true;
        Arrays.fill(used, false);
        }
    }

    return groups;
    }

    /**
     * Helper method that returns a List<Integer> given  
     * an array of primitive ints
     *
     * @array The array to convert to a List<Integer>
     */
    public static List<Integer> asList(int[] array) {
    List<Integer> boxed = new ArrayList<Integer>();

    for(int i = 0; i < array.length; i++) {
        boxed.add(array[i]);
    }

    return boxed;
    }

    /**
     * Generates the intial r combination in ascending order
     * i.e [1, 2, 3, 4, ..., r]
     *
     * @r The size of the intial combination
     */ 
    public static int[] initialCombination(int r) {
    int[] indices = new int[r];

    for(int i = 0; i < r; i++)
        indices[i] = i+1;

    return indices;
    }

    /**
     * Generates the next combination given an array of indices
     * 
     * @indicesIn The array of indices
     * @n         The size of this combination
     */
    public static int[] nextCombination(int[] indicesIn, int n) {
    int[] indices = (int[])indicesIn.clone();
    int r = indices.length;

    // find the rightmost index that is not at its final highest value
    int i = 0;
    for (i = r - 1; i >= 0; i--) {
        if (indices[i] != (i + n - r + 1)) {
        break;
        }
    }

    // return null if no more combinations exist
    if (i == -1)
        return null;

    // increment rightmost index
    indices[i]++;

    // reset all the indices to the right of indices[i]
    // to their smallest possible value.
    for (int j = i + 1; j < r; j++) {
        indices[j] = indices[j-1] + 1;
    }

    return indices;
    }

    /**
     * Generates all r-combinations of the indices array
     * 
     * @heroes The array of heroes wishes
     * @r      The length of the combination to generate
     */
    public static List<int[]> combination(List<Integer> heroes, int r) {
    List<int[]> combinations = new ArrayList<int[]>();
    int[] indices = initialCombination(r);

    while(indices != null) {
        combinations.add(indices);
        indices = nextCombination(indices, heroes.size());
    }

    return combinations;
    }
}
于 2012-12-28T19:01:00.233 に答える
1

まず、(Java の) 私の結果が最速です。 http://acm.timus.ru/rating.aspx?space=1&num=1922&lang=java

以前は十分に活用できなかったという事実は、ヒーローのリストを彼らの希望に従ってソートしたことです。

したがって、メイン ループを O(n^2) ではなく O(n) に変更するだけで済みます。

for (int i = 1; i <= ulen; i ++)
{
    if (w[0].wish <= i)
    {
        used[0] = true;
        search(0, i, 1);
        used[0] = false;
    }
}
于 2012-12-28T19:27:09.957 に答える