usaco camelot java

来源:互联网 发布:淘宝通过 拍摄脸部 编辑:程序博客网 时间:2024/06/05 19:47
/*ID: daniel.20LANG: JAVATASK: camelot*/import java.util.*;import java.io.*;public class camelot {    static int row,column;    static int king_x = -1;    static int king_y=-1;    static int table[][];    static int knights[];    static void initial(){        table = new int[row*column][row*column];        for(int i=0;i<row*column;i++){            Arrays.fill(table[i],99999999);            table[i][i] = 0;        }        for(int i=0;i<row*column;i++){            int dir[][] = {{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}};            int x = i/column;            int y = i%column;            for(int j=0;j<8;j++){                int t1 = x+dir[j][0];                int t2 = y+dir[j][1];                if(t1<0||t1>=row||t2<0||t2>=column) continue;                int tmp = t1*column+t2;                table[i][tmp] = 1;                table[tmp][i] = 1;            }        }    }    static void floyd(){        for(int k=0;k<row*column;k++){            for(int i=0;i<row*column;i++){                for(int j=0;j<row*column;j++){                    table[i][j] = Math.min(table[i][j], table[i][k]+table[k][j]);                }            }        }        //Dumper.print_2_arr(table, row*column, row*column);    }    static int pickup(int t){        int x = t/column;        int y = t%column;        int dis = Math.max(Math.abs(king_x-x), Math.abs(king_y-y)); //最远距离就是国王自己去目的地        int range = 3;        int result = dis;                           //result默认最大为国王自己去        for(int i=0;i<row*column;i++){             if(knights[i] == 0) continue;             for(int j=0;j<range;j++){                 for(int m=-j;m<=j;m++){            //枚举以国王为圆心的所有半径为range的点                     int tmp1 = king_x+m;                     if(tmp1<0||tmp1>=row) continue;                     for(int n=-j;n<=j;n++){                         int tmp2 = king_y+n;                         int tmp = tmp1*column+tmp2;                         if(tmp2<0||tmp2>=column) continue;                         int dist = Math.max(Math.abs(m), Math.abs(n));   //dist为国王自己去中途点的步数                         result = Math.min(dist+table[i][tmp]+table[tmp][t]-table[i][t],result); //国王自己走的加上骑士带国王走的,再减去骑士自己走的最短路                         if(result==0) {                                                         //就是骑士为了去接国王,两个人一共多走的步数                             return 0;                                                           //虽然骑士绕了远路,国王也动了,但这是最短的.                         }                                                                      //问题在于这个range的值其实应该是dis, 也就是国王自己走的步数                     }                                                                           //那样根本过不去,那是n^4的复杂度                 }             }        }        return result;    }    static void work() throws IOException{        int min = Integer.MAX_VALUE;        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("camelot.out")));        for(int i=0;i<row*column;i++){            int sum = 0;            for(int j=0;j<row*column;j++){                if(knights[j] == 0) continue;                sum+=table[i][j];            }                                   //找到最短路径,然后算骑士接国王需要多走几步            int re = pickup(i);            min = Math.min(min, sum+re);        }        System.out.println(min);        out.println(min);        out.close();    }    public static void main(String[] args) throws Exception {        Scanner cin = new Scanner(new File("camelot.in"));        column = cin.nextInt();        row = cin.nextInt();        knights = new int[row*column];        king_x = cin.next().charAt(0)-'A';        king_y = cin.nextInt()-1;        initial();        floyd();                                //floyd 枚举点对点        while(cin.hasNext()){            int t1 = cin.next().charAt(0)-'A';            int t2 = cin.nextInt()-1;            knights[t1*column+t2] = 1;        }        work();    }}

此题很坑,floodfill做惯了,这里转化成图论用floyd会方便很多.

很恶心的是,大部分的解法都是考虑king不会移动太多。

很明显,如果king移动太多步是不会出现的,但是一个合适的范围并无法确定,或者说没有合适的rule用来剪枝。

java把范围开到5都过不去,时间明显卡得太紧.


一开始以为自己怎么越来越水了,其实这题还是蛮困难的.

原创粉丝点击