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


/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
class Player {
    public static int distancies[][];
    public static int factoryCount;

    //Struct
    public static class BasicInfo {
        public int propietari, tropes, produccio;

        public BasicInfo(int propietari, int tropes, int produccio){
            this.propietari = propietari;
            this.tropes = tropes;
            this.produccio = produccio;
        }

        public BasicInfo(final BasicInfo bi){
            this.propietari = bi.propietari;
            this.tropes = bi.tropes;
            this.produccio = bi.produccio;
        }

        public int getPropietari(){
            return this.propietari;
        }
    }

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        factoryCount = in.nextInt(); // the number of factories
        int linkCount = in.nextInt(); // the number of links between factories
        int torn = 0;
        int num_bombes = 2;

        distancies = new int[factoryCount][factoryCount];

        // Initialize the distances from factories
        for(int i=0;i<factoryCount; i++){
            for(int j=0;j<factoryCount; j++){
                distancies[i][j]=1000;
            }           
        }

        for (int i = 0; i < linkCount; i++) {
            int factory1 = in.nextInt();
            int factory2 = in.nextInt();
            int distance = in.nextInt();

            // Communications are bidirectionals
            distancies[factory1][factory2] = distance;
            distancies[factory2][factory1] = distance;
        }

        BasicInfo factories[] = new BasicInfo[factoryCount];
        int atac_per_bomba;

        // game loop
        while (true) {
            atac_per_bomba = 0;
            int entityCount = in.nextInt(); // the number of entities (e.g. factories and troops)

            torn++;

            for (int i = 0; i < entityCount; i++) {
                int entityId = in.nextInt();
                String entityType = in.next();

                int arg1 = in.nextInt();
                int arg2 = in.nextInt();
                int arg3 = in.nextInt();
                int arg4 = in.nextInt();
                int arg5 = in.nextInt();

                if(entityType.equals("FACTORY")){
                    factories[entityId] = new BasicInfo(arg1, arg2, arg3);
                }else if(entityType.equals("BOOMB") && arg1==-1){
                    // Move my troops every turn that bomb is in travel, from my planet with most population to a neighbourg
                    atac_per_bomba = 1;
                }else{
                    // Mirar que fem amb les tropes
                    // Sumar-les quan van camint d'un planeta (2nd round)
                }
            }

            List<Integer> my_factories = new ArrayList<Integer>();
            // Search my factories
            for(int i=0; i<factoryCount; i++){
                if(factories[i].propietari==1){
                    my_factories.add(i);
                }
            }

            String accions[] = new String[factoryCount/2];
            int scores[] = new int[factoryCount/2];

            for(int k=0;k<scores.length; k++){
                accions[k] = "WAIT";
                scores[k] = 1000;
            }

            String accio_tmp = "WAIT";
            int score_tmp = 1000;
            String accio_tmp2 = "WAIT";
            int score_tmp2 = 1000;
            String accio_tmp3 = "WAIT";
            int score_tmp3 = 1000;
            int aux;
            int tropes = 1;
            List<Integer> max_tropes_meves = new ArrayList<Integer>();

            if(atac_per_bomba==1){
                // Search my factory with more troops
                max_tropes_meves = max_planeta_tropes(factories, 1, new ArrayList<Integer>());
            }

            // Heurístiques
            for(int i=0; i<my_factories.size(); i++){

                // If we have 0 troops in a factory, we don't need to do nothing with this planet
                if(factories[my_factories.get(i)].tropes > 0){

                    List<Integer> veins = veins(my_factories.get(i), 2, factories);

                    accio_tmp = "WAIT";
                    score_tmp = 1000;
                    accio_tmp2 = "WAIT";
                    score_tmp2 = 1000;
                    accio_tmp3 = "WAIT";
                    score_tmp3 = 1000;

                    for(int j=0; j<veins.size(); j++){
                        List<Integer> cami = distancia_min(my_factories.get(i), veins.get(j), 3);

                        aux = score_planeta(my_factories.get(i), veins.get(j), cami.get(cami.size()-1), factories);

                        // En aquest cas li donem major prioritat a meoure aquestes tropes a qualsevol lloc
                        if(max_tropes_meves.size()>1 && max_tropes_meves.get(1) == i && aux!=1000){
                            if(aux>5){
                                aux -= 5;
                            }
                            else{
                                aux = 1;
                            }
                        }

                        if(aux!=1000 && aux < score_tmp){

                            if(aux < score_tmp3 && aux > score_tmp2){
                                score_tmp3 = aux;
                                tropes = 1;
                                if(factories[veins.get(j)].propietari==0){
                                    tropes = factories[veins.get(j)].tropes + 2;
                                }
                                else{
                                    tropes = (cami.get(cami.size()-1) * factories[veins.get(j)].produccio) + factories[veins.get(j)].tropes + 2;
                                }

                                accio_tmp3 = "MOVE " + my_factories.get(i) + " " + veins.get(j) + " " + tropes;
                            }
                            else if(aux < score_tmp2 && aux > score_tmp){
                                score_tmp3 = score_tmp2;
                                accio_tmp3 = accio_tmp2;

                                score_tmp2 = aux;
                                tropes = 1;
                                if(factories[veins.get(j)].propietari==0){
                                    tropes = factories[veins.get(j)].tropes + 2;
                                }
                                else{
                                    tropes = (cami.get(cami.size()-1) * factories[veins.get(j)].produccio) + factories[veins.get(j)].tropes + 2;
                                }

                                accio_tmp2 = "MOVE " + my_factories.get(i) + " " + veins.get(j) + " " + tropes;                            
                            }
                            else if(aux < score_tmp){

                                score_tmp3 = score_tmp2;
                                accio_tmp3 = accio_tmp2;
                                score_tmp2 = score_tmp;
                                accio_tmp2 = accio_tmp;

                                score_tmp = aux;
                                tropes = 1;
                                if(factories[veins.get(j)].propietari==0){
                                    tropes = factories[veins.get(j)].tropes + 2;
                                }
                                else{
                                    tropes = (cami.get(cami.size()-1) * factories[veins.get(j)].produccio) + factories[veins.get(j)].tropes + 2;
                                }

                                accio_tmp = "MOVE " + my_factories.get(i) + " " + veins.get(j) + " " + tropes;
                            }
                        }
                        else if(score_tmp == 1000 && aux==1000){
                            accio_tmp = "WAIT";
                        }
                    }

                    if(!accio_tmp.equals("WAIT")){

                        // If we have multiple troops in a planet, we allow to three actions
                        if(factories[my_factories.get(i)].tropes>15){
                            if(!accio_tmp2.equals("WAIT")){
                                accio_tmp += ";" + accio_tmp2;
                            }
                            if(!accio_tmp3.equals("WAIT")){
                                accio_tmp += ";" + accio_tmp3;
                            }
                        }

                        if(score_tmp < scores[0]){
                            for(int k=scores.length-1;k>0; k--){
                                if(!accions[k-1].equals("WAIT")){
                                    scores[k]=scores[k-1];
                                    accions[k]=accions[k-1];
                                }
                            }
                            scores[0] = score_tmp;
                            accions[0] = accio_tmp;     
                        }
                        else{
                            for(int k=scores.length-1;k>=1; k--){

                                if(score_tmp < scores[k] && score_tmp>scores[k-1]){

                                    for(int kk=scores.length-1;kk>k; kk--){
                                        if(!accions[kk-1].equals("WAIT")){
                                            scores[kk]=scores[kk-1];
                                            accions[kk]=accions[kk-1];
                                        }
                                    }

                                    scores[k] = score_tmp;
                                    accions[k] = accio_tmp;
                                    break;          
                                }
                            }
                        }
                    }
                }
            }


            // Write an action using System.out.println()
            // To debug: System.err.println("Debug messages...");

            // Any valid action, such as "WAIT" or "MOVE source destination cyborgs"

            String accio = accions[0];

            for(int k=1;k<accions.length; k++){
                if(!accions[k].equals("WAIT")){
                    accio += ";" + accions[k];
                }
                else{
                    break;
                }
            }

            // Final bomb
            if(torn>180 && num_bombes>0){
                List<Integer> max_tropes = max_planeta_tropes(factories, -1, new ArrayList<Integer>());
                if(max_tropes.size()>1 && max_tropes.get(1)>10){
                    List<Integer> veins_desti = veins(max_tropes.get(0), 1, factories);

                    // We could calculate which neighbourg is more near, but would be to much predictive
                    // Then I send it from random neighbourg
                    if(veins_desti.size()>0){
                        Random rand = new Random();
                        int orig_aleatori = rand.nextInt(veins_desti.size());
                        accio += ";BOMB " + veins_desti.get(orig_aleatori) + " " + max_tropes.get(0);
                        num_bombes--;
                    }
                }
            }
            // We search for enemy planets with a lot of troops
            else if(num_bombes>0){
                List<Integer> max_tropes = max_planeta_tropes(factories, -1, new ArrayList<Integer>());

                // If same planet have more than 20 troops is a good candidate
                if(max_tropes.size()>1 && max_tropes.get(1)>20 && factories[max_tropes.get(0)].produccio>1){
                    List<Integer> veins_desti = veins(max_tropes.get(0), 1, factories);

                    // We could calculate which neighbourg is more near, but would be to much predictive
                    // Then I send it from random neighbourg
                    if(veins_desti.size()>0){
                        Random rand = new Random();
                        int orig_aleatori = rand.nextInt(veins_desti.size());
                        accio += ";BOMB " + veins_desti.get(orig_aleatori) + " " + max_tropes.get(0);
                        num_bombes--;
                    }
                }
            }

            System.out.println(accio);
        }
    }

    // tipus = 3 -> qualsevol tipus
    // tipus = 2 -> neutrals o enemics
    // tipus = 1 -> meus
    // tipus = 0 -> neutrals
    // tipus = -1 -> enemics
    static List<Integer> veins(int origen, int tipus, BasicInfo[] factories){

        List<Integer> veins = new ArrayList<Integer>();

        for(int i=0; i<factoryCount; i++){
            if(distancies[origen][i]!=1000){
                if( (tipus<2 && tipus==factories[i].propietari) || tipus==3){
                    veins.add(i);
                }
                else if(tipus==2 && (factories[i].propietari==-1 || factories[i].propietari==0) ){
                    veins.add(i);
                }
            }
        }

        return veins;
    }


    // Retornem el camíí méés curt entre origen i destí, i l'últim element q retornem a la llista es la logitud
    static List<Integer> distancia_min(int origen, int desti, int lvl){

        int min = distancies[origen][desti];
        List<Integer> cami = new ArrayList<Integer>();

        cami.add(origen);
        cami.add(desti);

        // Limitem a 3 nivells de profunditat
        if(lvl<3){
            for(int i=0; i<factoryCount; i++){
                if(distancies[origen][i]!=0){
                    List<Integer> aux = distancia_min(i, desti, lvl+1);
                    if(min > aux.get(aux.size()-1) + distancies[origen][i]){
                        min = aux.get(aux.size()-1) + distancies[origen][i];
                        cami.remove(cami.size()-1);
                        cami.addAll(aux);
                    }
                }
            }
        }

        // L'últim element q retornem es la logitud
        cami.add(min);

        return cami;
    }


    static int score_planeta(int origen, int desti, int distancia, BasicInfo[] factories){    
        int score;

        if(factories[desti].propietari == -1){
            if( (distancia * factories[desti].produccio) + factories[desti].tropes > factories[origen].tropes){
                score = 1000;
            }
            else{
                score = ((distancia * factories[desti].produccio) + factories[desti].tropes) - (factories[desti].produccio*3) + distancia;

                // Si és de l'enemic enlloc de neutral, li donem un plus
                score--;
            }
        }
        else if(factories[desti].propietari == 0){
            if(factories[desti].tropes > factories[origen].tropes){
                score = 1000;
            }
            else{
                score = factories[desti].tropes - (factories[desti].produccio*3) + distancia;
            }
        }
        // No passarà mai
        else{
            score = 1000;
        }

        return score;
    }

    // si frinedly = 1 -> planetes meus
    // si frinedly = -1 -> planetes enemics
    // descartar -> Listat d'identificadors a no tenir en compte (probablement pq hi estem fent altres accions ja)
    // Retorna id, num_tropes
    static List<Integer> max_planeta_tropes(BasicInfo[] factories, int friendly, List<Integer> descartar){    
        List<Integer> retornar = new ArrayList<Integer>();
        int max_tropes = 0;
        int max_id = -1;

        for(int i=0; i<factoryCount; i++){
            if(factories[i].propietari == friendly && !descartar.contains(i) && max_tropes<factories[i].tropes ){
                max_tropes = factories[i].tropes;
                max_id = i;
            }
        }

        retornar.add(max_id);
        retornar.add(max_tropes);

        return  retornar;
    }
}

Built With

Share this project:

Updates