转载请注明出处
一. 题目翻译
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)
单独的一行包含一个整数表示所需木板的最小总长度。
SAMPLE INPUT:
4 50 18
3
4
6
8
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();
}
}
}