Zdrojový kód zadania od G. Tela

Created: 2009-11-27 - 17:38

//-----------------------------------------------------------
// Pretty text / paragraph formatting algorithm in O(m*n)
// where m is line length and n is total count of words.
// This algorithm uses dynamic programming.
//

// coding: Pavol Rajzák
// special thanks: Ján Jerguš, Maroš Andrejko, Marek Daňko
// happy birthday LM
//-----------------------------------------------------------


import java.util.*;

public class TextFormatting {

    public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    int n = s.nextInt();
    for (int i = 0; i < n; i++) {
        int M = s.nextInt();
        String p = s.next();
        String text = s.nextLine();
        format(M, p+text);
        System.out.println();
//        Testovacie vzorky pre rychle overenie (treba zakomentovat predchadzajucu cast a odkomentovat tuto)
//        int M = 30;
//        String text = "This text is allowed to be wider. To fill multiple lines, we need lots of words.";
//        format(M, text);
//        System.out.println();
//        M = 13;
//        text = "Sometimes the solution requires more thought.";
//        format(M, text);
//        System.out.println();
//        M = 11;
//        text = "The short words are the best. And the old words, when short, are best of all. (Churchill)";
//        format(M, text);
//        System.out.println();
    }
    }

    public static void format(int M, String word){
    //Priprava slov, urcenie poctu slov, zapamätanie si povodneho M
    String[] words = word.split(" ");
    int cntWords = words.length;
    int MP = M;
    
    //jedna tabulka sluzi na pamätanie docasnych vysledkov, druha
    //uchovava informacie pre neskorsie vybudovanie cesty
    int[] matrix = new int[cntWords+1];
    int[] rebuild = new int[cntWords+1];
    
    //Nastavenie pola hodnot, na maximalne hodnoty
    for (int i = 0; i < matrix.length; i++) {
        matrix[i] = Integer.MAX_VALUE;
    }
    
    //priznak urcujuci, ci spracuvavame posledny riadok    
    boolean last = true;
    
    //cyklus zacina pri poslednom slove
    for(int i = cntWords; i > 0; i--){
        
        //Ak spracuvava posledny riadok, t.j. je mozne umiestnit slovo
        //do posledneho riadku, nastavi hodnotu v matici na 0 pre dane
        //slovo. To znamena, ze skaredost spojena s tymto slovom bude
        //nulova, pretoze je v poslednom riadku
        if(last){
        if(M - words[i-1].length() >= 0){
            matrix[i] = 0;
            M = M - words[i-1].length() - 1;
        } else {
            last = false;
            M = MP;
            i++;
        }
        }
        //Ak presiel na spracovanie ostatnych riadkov, zistuje, aka je
        //minimalna skaredost pre dane j-te slovo, ak zacina v danom
        //riadku. Potom sa snazi pridavat dalsie slova, ak sa zmestia
        //do daneho riadku a zistuje, ci skaredost po pridani daneho
        //slova nebude mensia ako pred tym. Ak ano, tak vymeni hodnoty
        //a do tabulky rebuild prepise povodnu hodnotu, ktora bude
        //znacit az kam sa moze z daneho slova dostat.
        else {
        int j = i;
        rebuild[i] = 1;
        while(true){
            if(M - words[j-1].length() >= 0){
            M = M - words[j-1].length() - 1;
            if(matrix[i]<(matrix[j+1] + (int)Math.pow(M+1,2))){
            } else {
                matrix[i] = matrix[j+1] + (int)Math.pow(M+1,2);
                rebuild[i] = j;
            }
            j++;
            } else {
            break;
            }
        }
        M = MP;
        }
    }
    
    //Postupne pride az ku rieseniu, ktore sa nachadza v prvom poli tabulky
    System.out.println(matrix[1]);
    
    //Samotny vypis bude fungovat tak, ze si zisti, na ktore slovo sa
    //vie dostat z aktualneho slova. Napr. ak sa vie dostat z prveho
    //slova na sieste, tak vypise prvych sest slov do jedneho riadku,
    //prejde na dalsi riadok a pozrie sa kam sa az moze dostat zo
    //siesteho slova. Bud tam bude mat hodnotu kam sa az moze dostat
    //alebo nulu, co znaci, ze moze vypisovat slova az do konca.
    int next = rebuild[1];
    for (int i = 0; i < words.length; i++) {
        if(i
        System.out.print(words[i]+" ");
        } else {
        System.out.println();
        System.out.print(words[i]+" ");
        next=rebuild[next+1];
        if(next==0)
            next=cntWords;
        }
    }
    
    }

}