poj1009
2014-05-24
题目
网址:
http://poj.org/problem?id=1009
参考网站:
http://blog.csdn.net/rongyongfeikai2/article/details/7182098
代码及其详细注释
import java.io.*; import java.math.*; import java.util.*; /* 用来记录数据的类。 * 1.记录输入数据的数值和长度 * 2.记录输出数据的位置和值 * 变量名没取好,见谅*/ class Record{ private int number; private int count; public Record(int number, int count){ this.number = number; this.count = count; } public int getNum(){ return number; } public int getCount(){ return count; } public String toString(){ return number +" "+count; } } /* 实现比较接口的类 * 用来给输出数据按照位置的大小排序*/ class RecordComparator implements Comparator{ public int compare(Object o1, Object o2){ Record r1 = (Record)o1; Record r2 = (Record)o2; if(r1.getNum() > r2.getNum()) return 1; else if(r1.getNum() == r2.getNum()) return 0; else return -1; } } public class Main{ private static int width = 0; // 数据宽度 private static int Num = 0; // 记录数据的总的个数 public static void main(String[] args) throws IOException{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String line = ""; Main main = new Main(); while(true){ line = in.readLine(); if("0".equals(line)){ System.out.println("0"); // 打印结束标志 break; } width = Integer.parseInt(line); System.out.println(width); ArrayListpairs = new ArrayList (); // 输入数据,放在arraylist中 ArrayList outPairs = new ArrayList (); // 输出数据 int pos = 1; // 起始位置,每轮从1开始 Num = 0; // 起始个数为0 //读入每一轮的数据到pairs,并计算出总数据的个数 while(true){ line = in.readLine(); if("0 0".equals(line)) break; String[] data = line.split(" "); int number = Integer.parseInt(data[0]); int count = Integer.parseInt(data[1]); Record r = new Record(number, count); pairs.add(r); Num += r.getCount(); } //只读取改变了的那些值的输出值,并计算被它所影响的那些数据的输出值 for(int i = 0;i <= pairs.size(); i++){ // 将位置换算成行和列,从0开始 int row = (pos - 1) / width; int col = (pos - 1) % width; //计算元素在最后一列,且该元素下两行还有数据的那些的数值,因为这些值如有改变的话,会影响它的下两行的第一个值的输出值 if(col == width -1){ if((row + 2) * width < Num){ Record rd = new Record(pos + width + 1, main.calNode(pairs, pos + width + 1, row + 2, 0)); outPairs.add(rd); } } //计算改变了的数据的值及其受它所影响的值的输出值 for(int m = row - 1; m <= row + 1; m++){ for(int n = col - 1; n <= col + 1; n++){ int myPos = m * width + n +1; if((m >= 0)&&(n >= 0)&&(n < width)&&(myPos <= Num)){ // 关键判断 Record rd = new Record(myPos, main.calNode(pairs, myPos, m, n)); outPairs.add(rd); } } } // 计算出下一个值改变了的数据 if(pairs.size() != i){ pos += pairs.get(i).getCount(); } } //给输出数据按照位置大小,从小到大排序,以便输出 Collections.sort(outPairs, new RecordComparator()); //输出结果数据。注意最后一批数据 int cur = 0; for(int i = 0; i < outPairs.size(); i++){ if(outPairs.get(i).getCount() == outPairs.get(cur).getCount()){ continue; } System.out.println(outPairs.get(cur).getCount()+" "+(outPairs.get(i).getNum() - outPairs.get(cur).getNum())); cur = i; } System.out.println(outPairs.get(cur).getCount()+" "+(Num - outPairs.get(cur).getNum() + 1)); //打印该轮的最后一批数据 System.out.println("0 0"); // 打印该轮结束标志 } } /**计算该数据的输出值,参数是数据的行和列,以及它所在的位置**/ public int calNode(ArrayList pairs, int pos, int row, int col){ int result = 0; for(int i = row - 1; i <= row + 1; i++){ for(int j = col -1; j <= col + 1; j++){ int tempPos = i * width + j + 1; // 要和该位置数据比较的其他元素的位置 if(pos == tempPos){ continue; } if(i>=0&&j>=0&&j<width&&tempPos<=Num){ //关键判断 int value = Math.abs(getValue(pairs, tempPos) - getValue(pairs, pos)); if(result < value) result = value; } } } return result; } /** 给定一个位置,得到该位置处的数据的信息。如,数值和长度信息 **/ public int getValue(ArrayList pairs, int pos){ int i = 0, j = 0; for(i = 0; j < pos; i++){ j += pairs.get(i).getCount(); } return pairs.get(i - 1).getNum(); } } </pre> **总结** * 不需要弄两个二维数组存放输入输出数据,直接用2个list搞定,节省了内存开销。 * 用一个记录位置信息的变量,来换算出每个数据的坐标(行和列)。 * 添加类的比较器,用一个类去实现Comparator类,以及其int compare()方法;然后调用Collections的sort()方法,打到快速排序的效果。 * 计算每个点的输出值的时候,采用3行3列的方法,并在其中添加关键判断来过滤掉不应该有的值。 * 收获多多啊。