USACO - 1.4.2 - The Clocks

 

原创文章转载请注明出处

摘要: 枚举,暴力破解

一. 题目翻译

1. 描述:
          考虑将如此安排在一个 3 x 3 行列中的九个时钟:
          
          目标要找一个最小的移动顺序将所有的指针指向12点。下面原表格列出了9种不同的旋转指针的方法,每一种方法都叫一次移动。选择1到9号移动方法,将会使在表格中对应的时钟的指针顺时针旋转90度。
          移动方法  受影响的时钟 
          1        ABDE
          2        ABC
          3        BCEF
          4        ADG
          5        BDEFH
          6        CFI
          7        DEGH
          8        GHI
          9        EFHI

2. 格式:

          INPUT FORMAT:

          (file clocks.in)
          第1-3行: 三个空格分开的数字,每个数字表示一个时钟的初始时间,3,6,9,12。数字的含意和上面第一个例子一样。

          OUTPUT FORMAT:

          (file clocks.out)
          单独的一行包括一个用空格分开的将所有指针指向12:00的最短移动顺序的列表。
          如果有多种方案,输出那种使其连接起来数字最小的方案。(举例来说5 2 4 6 < 9 3 1 1)。

3. SAMPLE:
          SAMPLE INPUT:
9 9 12
6 6 6
6 3 6
          SAMPLE OUTPUT:
 4 5 8 9
          
二.  题解
1. 题意理解(将问题分析清楚,大致用什么思路):
           题目数据的输入量比较小,可以直接使用暴力枚举的方式计算答案。对于A-I的每一种移动方式,使用4次等价于没有使用。所以按照A-I的顺序做9重循环即可,每一重至多做三次。最后判断产生的结果是否与答案的要求相等。

 

 

2. 启示:
           其实刷题过程中,如果数据量不是很大情况时候,可以直接使用暴力枚举的方式。需要注意的是,对于每一种状态,要通过分析发现其上限,例如这道题目当中移动4次等于没有移动。

三.  代码
/*
ID:fightin1
LANG:JAVA
TASK:clocks
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Scanner;

public class clocks {
	static int[][] move = {{3,3,0,3,3,0,0,0,0},
		{3,3,3,0,0,0,0,0,0},
		{0,3,3,0,3,3,0,0,0},
		{3,0,0,3,0,0,3,0,0},
		{0,3,0,3,3,3,0,3,0},
		{0,0,3,0,0,3,0,0,3},
		{0,0,0,3,3,0,3,3,0},
		{0,0,0,0,0,0,3,3,3},
		{0,0,0,0,3,3,0,3,3}
		};
	public static void main(String[] args) {
		try {
			Scanner in = new Scanner(new BufferedReader(new FileReader("clocks.in")));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("clocks.out")));
			int[] init = new int[9];
			for (int i=0;i<9;i++){
				init[i] = in.nextInt();
			}
			// 如果使用bfs有严重的超时 与 超空间的问题
			boolean stop = false;
			for (int i=0;i<=3&&!stop;i++){
				for (int j=0;j<=3&&!stop;j++){
					for (int k=0;k<=3&&!stop;k++){
						for (int l=0;l<=3&&!stop;l++){
							for (int m=0;m<=3&&!stop;m++){
								for (int n=0;n<=3&&!stop;n++){
									for (int p=0;p<=3&&!stop;p++){
										for (int q=0;q<=3&&!stop;q++){
											for (int r=0;r<=3&&!stop;r++){
												int temp[] = new int[9];
 												boolean equals = true;
												for (int z=0;z<9;z++){
 													temp[z] = (init[z] +
 															  move[0][z]*i+
 													          move[1][z]*j+
 													          move[2][z]*k+
 													          move[3][z]*l+
 													          move[4][z]*m+
 													          move[5][z]*n+
 													          move[6][z]*p+
 													          move[7][z]*q+
 													          move[8][z]*r)%12;
 													if (temp[z]==0){
 														temp[z] = 12;
 													}
 													if (temp[z]!=12){
 														equals = false;
 														break;
 													}
												}
												if (equals){
													stop = true ;
													int[] out = {i, j, k, l, m,  n, p , q  ,r};
													print( pw , out);
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			pw.close();
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void print(PrintWriter pw , int[] out){
		StringBuffer sb = new StringBuffer();
		for (int i=0;i<out.length;i++){
			for (int j=0;j<out[i];j++){
				sb.append(i+1+" ");
			}
		}
		sb.deleteCharAt(sb.length()-1);
		pw.println(sb);
		System.out.println(sb);
	}
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值