[USACO]clocks

提交了15次,一直超时。后来参考别人的解题思路,和自己的做了对比,复杂度一致,差在一个常数倍上。

采用BFS算法,和别人的想法有些不太一样。

用一个树来代表全部有效的操作步骤,从根到每个叶的路径为一个有效的操作,每个节点的value为一个二维数组,数组的第一个元素代表该节点子节点值的取值下限,如若为4,则第一个子树的值应当为4,第二个为5,一次类推;第二个元素代表从根节点到本节点第一个元素值出现的次数,若次数达到3次,则子树的取值下限增1,如若[3,3],则第一个子树取值为[4,1]。

用BFS遍历该树可以保证得到的操作步骤是按照数值递增的,这样在获得第一个有效的路径时即可以结束遍历。

树结构如下:

《[USACO]clocks》

方法说明:pre_process()对每个操作进行预处理,每步转换成相应位为011的二进制码。

process()按照相应method转动相应钟表。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;

public class clocks {
    private static final String[] MOVES = { "ABDE", "ABC", "BCEF", "ADG",
	    "BDEFH", "CFI", "DEGH", "GHI", "EFHI" };
    private static int[][] iMOVES;
    private static final int FULL = (1 << 27) - 1;
    private static int[] optimal_steps ;

    public static void main(String[] args) throws IOException {
    long start = System.currentTimeMillis();
	BufferedReader br = new BufferedReader(new FileReader("clocks.in"));
	FileWriter fout = new FileWriter("clocks.out");

	String init = new String();
	for (int i = 0; i < 3; i++) {
	    init +=  " "+br.readLine() ;
	}
	int clocks =pre_process( init);
	//0:move;1:counter;2:clocks;3-11:times of each method 
	int[] moves = new int[12]; 
	moves[2] = clocks;
	// Define three Queue
	LinkedList<int[]> queue = new LinkedList<int[]>();
	// Initial queues
	queue.add(moves);
	while (queue.size() > 0) {
	    int[] move = queue.poll();
	    int clock = move[2];
	    if (clock == 0) {
	        optimal_steps =move;
	        break;
	    }
	    if (move[1] == 3 && move[0] == 8)
	        continue;
	    if (move[1] < 3) {
	        int[] moves_tmp = move.clone();
	        int clocks_tmp=process(clock, move[0]);
    		moves_tmp[1]++;
    		moves_tmp[2]=clocks_tmp;
    		moves_tmp[move[0]+3]++;
    		queue.add(moves_tmp);
    	   }
	    for (int i = (int)move[0] + 1; i < 9; i++) {
	        int[] moves_tmp = move.clone();
	        int clocks_tmp =process(clock, i);
    		moves_tmp[0] = i;
    		moves_tmp[1] = 1;
    		moves_tmp[2] = clocks_tmp;
    		moves_tmp[i+3]++;
    		queue.add(moves_tmp);
	    }
	}
	//output result
	if (optimal_steps == null)
	    fout.write("NONE\n");
	else {
	    StringBuffer result = new StringBuffer();
	    for(int i =0;i<9;i++) {
	        for(int j =0;j<optimal_steps[i+3];j++) {
	            result.append((i+1)+" ");
	        }
	    }
	    fout.write(result.substring(0,result.length()-1) + "\n");
	}
	fout.flush();
	fout.close();
	br.close();
	long end = System.currentTimeMillis();
	System.out.println(end- start);
	System.exit(0);
    }

    private static int pre_process(String init) {

	String[] str = init.substring(1).split(" ");
	int clock = 0;
	int counter = 0;
	for (int i = 0; i < 9; i++) {
	    clock += (((Integer.parseInt(str[i]) / 3) & 3)<< (3 * i) );
	    if (clock != 0) {
	        counter++;
	    }
	}
	iMOVES = new int[9][3];
	for(int i =0;i<9;i++) {
	    char[] chars = MOVES[i].toCharArray();
	    for(char c: chars) {
	        iMOVES[i][0] += (1<<((c-'A')*3));
	    }
	    iMOVES[i][2] = iMOVES[i][0]+(iMOVES[i][0]<<1)+(iMOVES[i][0]<<2);
	    iMOVES[i][1] = iMOVES[i][0]+(iMOVES[i][0]<<1);
	}
	return clock;
    }

    /**
     * @descrpition:apply method in clocks.
     * 
     * */
    private static int process(int clocks, int method) {
	   return (((clocks&iMOVES[(int)method][2])+iMOVES[(int)method][0])&iMOVES[(int)method][1])+(clocks&(FULL-iMOVES[(int)method][2]));
    }
}

点赞