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