USACO - 1.3.2 - Barn Repair

 

转载请注明出处

摘要:贪心

一. 题目翻译

1. 描述:

          在一个夜黑风高,下着暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 剩下的牛棚一个紧挨着另一个被排成一行,牛就住在里面过夜。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自门遗失以后,农民约翰必须尽快在牛棚之前竖立起新的木板。 他的新木材供应商将会供应他任何他想要的长度,但是供应商只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。

          给出:可能买到的木板最大的数目M(1<= M<=50);牛棚的总数S(1<= S<=200); 牛棚里牛的总数C(1 <= C <=S);和牛所在的牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。 输出所需木板的最小总长度作为答案。

2. 格式:

          PROGRAM NAME:barn1

          INPUT FORMAT:

 

          (file barn1.in)

          1 行: M , S 和 C(用空格分开)  

          2 到 C+1行:  每行包含一个整数,表示牛所占的牛棚的编号

          OUTPUT FORMAT:

 

          (file barn1.out)

          单独的一行包含一个整数表示所需木板的最小总长度。

3. SAMPLE:
          SAMPLE INPUT:
4 50 18




14
15 
16 
17 
21
25 
26 
27 
30 
31 
40 
41 
42 
43
          SAMPLE OUTPUT:
               25


二.  题解
1. 题意理解(将问题分析清楚,大致用什么思路):
          这道题目的核心还是贪心。初始条件是用一块板子盖住所有的牛,然后找出当前所有牛当中空隙最大的为界将木板分为两块,结束条件是到所有的可用木板用完或者已经没有空隙。

2. 具体实现(具体实现过程中出现的问题):
          用一个数组cowsInStalls记录所有奶牛在哪个牛栏,并对这个数组排序。然后针对排序后的数组产生一个记录相邻奶牛之间距离的数组dist。
          算法初始使用一块木板覆盖所有的牛(木板总长度result等于cowsInStalls[0]到cowsInStalls[cows - 1]之间的距离)。然后找出当前最大的相邻牛之间的间隙(使用数组dist,可以先排序),然后以此为界将木板分割(更新木板的总长度,用原有总长度result减去当找出的最大间隙dist[i]即可)。

3. 需要注意的细节:
          要特别注意程序中循环停止的条件。有两种情况会造成循环停止:1. 所有的木板已经用完(i<(boards-1)) 2.牛之间已经没有了间隙(i<dist.length)。

4. 启示
          贪心算法的正确性未验证,希望能有高手补充。

三.  代码
package session_1_3_2;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

public class barn1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			Scanner in = new Scanner(new BufferedReader(new FileReader("F:\\UCASO\\temp\\barn1.in")));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("F:\\UCASO\\temp\\barn1.out")));
			
			int boards = in.nextInt(); // 可用的木板数
			int stalls = in.nextInt(); // 有多少牛栏
			int cows = in.nextInt(); // 有多少头奶牛
			int[] cowsInStalls = new int[cows]; //奶牛i在哪个牛栏里
			int[] dist = new int[cows-1]; // 相邻奶牛之间的距离
			
			for (int i=0;i<cows;i++){
				cowsInStalls[i] = in.nextInt();
			}
			// 这里要特别注意, 有可能出现不按顺序的奶牛栏,需要排序
			Arrays.sort(cowsInStalls); 
			for (int i=1;i<cows;i++){
				dist[i-1] = cowsInStalls[i] - cowsInStalls[i-1];
			}
			Arrays.sort(dist);//对奶牛之间的距离排序
			
			int result = cowsInStalls[cows-1] - cowsInStalls[0] + 1;//初始总木板长度
			//这里要充分考虑数组越界的情况,要做两种情况的判断
			for (int i=0;i<(boards-1)&i<dist.length;i++){//找出距离最远的两头奶牛,已他们为界,将木板分为两块。直到所有木板用完,或者已经没有空隙
				result = result + 1 - dist[dist.length-1-i];//
			}
			pw.println(result);
			pw.close();
			in.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值