usaco/ 1.3 milk/barn1

package chapter1_3;

/*
 ID: chicc991
 LANG: JAVA
 TASK: milk
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.TreeSet;

public class milk
{
	private Scanner sc;
	private PrintWriter out;
	private TreeSet<milker> arr;

	public static void main(String[] args) throws Exception
	{
		milk main = new milk();
	}

	public milk() throws Exception
	{
		sc = new Scanner(new FileReader(new File("data/milk.in")));
		out = new PrintWriter(new BufferedWriter(
				new FileWriter("data/milk.out")));
		while (sc.hasNext()) {
			double n = sc.nextDouble();
			int m = sc.nextInt();

			if (n == 0 || m == 0) {
				out.println(0);
				out.close();
				System.exit(0);
			}

			arr = new TreeSet<milker>();
			for (int i = 0; i < m; i++)
				arr.add(new milker(sc.nextDouble(), sc.nextDouble()));
			
			double sum = 0;
			milker mm = null;
			for (milker mi:arr) {
				n -= mi.count;

				if (n > 0)
					sum += mi.cost();
				else {
					mm=mi;
					break;
				}
			}
			sum += mm.price * (n + mm.count);
			out.println((int) sum);

		}
		out.close();
		sc.close();

	}

}

class milker implements Comparable<milker>
{
	public double price;
	public double count;

	public milker(double price, double count)
	{
		this.price = price;
		this.count = count;
	}

	@Override
	public int compareTo(milker o)
	{
		if (this.price >= o.price)
			return 1;
		else
			return -1;

	}

	public double cost()
	{
		return price * count;
	}

}

簡單的貪心策略。注意如果用數組讀入在排序會超時,可以直接用紅黑樹插入。

特殊解法:因爲單價的範圍爲(0-1000)且爲整數,所以可以開一個1001的數組,下標爲單價,存儲的值爲數量。

package 優化;

/*
 ID: chicc991
 LANG: JAVA
 TASK: milk
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Scanner;

public class milk
{
	public static void main(String[] args) throws Exception
	{
		Scanner sc = new Scanner(new FileReader(new File("data/milk.in")));
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
				"data/milk.out")));
		while (sc.hasNext()) {
			double n = sc.nextDouble();
			int m = sc.nextInt();

			if (n == 0 || m == 0) {
				out.println(0);
				out.close();
				System.exit(0);
			}

			int[] a = new int[1001];
			for (int i = 0; i < m; i++)
				a[sc.nextInt()] += sc.nextInt();

			int sum = 0;
			int j = 0;
			for (int i = 0; i < 1001; i++) {
				n -= a[i];
				if (n > 0)
					sum += i * a[i];
				else {
					j = i;
					break;
				}
			}
			sum += (n + a[j]) * j;
			out.println(sum);
		}
		out.close();
	}
}

barn1

package chapter1_3;

/*
 ID: chicc991
 LANG: JAVA
 TASK: barn1
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.PriorityQueue;
import java.util.Scanner;

public class barn1
{
	private Scanner sc;
	private PrintWriter out;
	private PriorityQueue<zeroSet> que;

	public static void main(String[] args) throws Exception
	{
		barn1 main = new barn1();
	}

	public barn1() throws Exception
	{
		sc = new Scanner(new FileReader(new File("data/barn1.in")));
		out = new PrintWriter(new BufferedWriter(new FileWriter(
				"data/barn1.out")));
		while (sc.hasNext()) {

			int m = sc.nextInt();
			int s = sc.nextInt();
			int c = sc.nextInt();
			int[] a = new int[s + 1];
			for (int i = 0; i < c; i++)
				a[sc.nextInt()] = 1;

			int i = 0;
			int j = s;
			while (a[i] == 0 && i < s)
				i++;
			while (a[j] == 0 && j > 0)
				j--;

			if (m != 1) {
				que = new PriorityQueue<zeroSet>(m - 1);

				int k = i;
				int l = i;
				int line = 0;
				while (k <= j) {
					if (a[k++] == 1) {
						line = k - l - 1;
						l = k;
						if (line > 0) {
							zeroSet zt = new zeroSet(line);
							if (que.size() == m - 1) {
								if (zt.compareTo(que.peek()) > 0) {
									que.poll();
									que.offer(zt);
								}
							} else
								que.offer(zt);

						}
						continue;
					}
					while (a[k] == 0)
						k++;

				}
				int sum = 0;
				for (zeroSet zt : que)

					sum += zt.dis;

				out.println(j - i + 1 - sum);
			} else {
				out.println(j - i + 1);
			}

		}
		out.close();
	}

	class zeroSet implements Comparable<zeroSet>
	{
		public int dis;

		public zeroSet(int dis)
		{
			this.dis = dis;
		}

		@Override
		public int compareTo(zeroSet o)
		{
			return this.dis - o.dis;
		}
	}
}

長度最短,木板一定全用上。只需要找出m-1個最長的連續0,將他們去掉即可。構造大小爲m-1的小頂堆。


/*
 ID: chicc991
 LANG: JAVA
 TASK: barn1
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class barn1
{
	private Scanner sc;
	private PrintWriter out;
	private ArrayList<Integer> arr;

	public static void main(String[] args) throws Exception
	{
		barn1 main = new barn1();
	}

	public barn1() throws Exception
	{
		sc = new Scanner(new FileReader(new File("data/barn1.in")));
		out = new PrintWriter(new BufferedWriter(new FileWriter(
				"data/barn1.out")));
		while (sc.hasNext()) {

			int m = sc.nextInt();
			int s = sc.nextInt();
			int c = sc.nextInt();

			arr = new ArrayList<Integer>(c + 1);
			arr.add(0);
			for (int i = 0; i < c; i++)
				arr.add(sc.nextInt());
			
			
			Collections.sort(arr);

			int[][] f = new int[m + 1][c + 1];

			for (int i = 0; i <= c; i++)
				f[1][i] = arr.get(i) - arr.get(1) + 1;

			for (int i = 0; i <= m; i++)
				f[i][1] = 1;

			for (int i = 2; i <= m; i++)
				for (int j = 2; j <= c; j++)
					f[i][j] = Math.min(f[i - 1][j - 1] + 1,
							f[i][j - 1] + arr.get(j) - arr.get(j - 1));

			out.println(f[m][c]);

		}
		out.close();
		sc.close();
	}
}

以上爲動態規劃解法。

構建最優子結構:

f[i][j] = Math.min(f[i - 1][j - 1] + 1,f[i][j - 1] + arr.get(j) - arr.get(j - 1));

其中f[i][j]表示i塊木板覆蓋j頭牛需要的最短長度,其值爲i-1塊木板覆蓋j-1頭牛後再用一塊木板覆蓋一頭牛,或者延長一塊木板到第j頭牛所在牛欄,取2者的較小值

初始條件

(1)只有1塊木板時,最小長度爲第j頭牛所在牛欄減去第一頭牛所在牛欄

(2)只有1頭牛時,最小長度爲1

点赞