提交 1395091e 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 0e3d2209
package Water;
public class 日期差 {
public static void main(String[] args) {
}
}
......@@ -3,12 +3,13 @@ package dp;
import java.util.*;
/**
* 带权的区间调度
* 带权的区间调度(挺重要,细节需要注意)
* https://blog.csdn.net/hongchh/article/details/52914507
* 存在单一资源R,有n个需求{1, 2, …, n},每个需求指定一个开始时间bi与一个结束时间ei,在时间区间[bi, ei]内该需求想要占用资源R,资源R一旦被占用则无法被其他需求利用。每个需求i带有一个权值vi,代表该需求被满足之后能够带来的价值或者贡献。如果两个需求的时间区间不重叠,那么它们是相容的。带权值的区间调度问题即,对上面所描述的情境,求出一组相容子集S使得S中的区间权值之和最大。
* <p>
* 解决此类问题一般采用动态规划的思路,执行步骤分以下几个阶段:
* <p>
* 对所有的需求按照结束时间排序。
* 对所有的需求按照结束时间升序排序。
* 求出所有需求前面所有的需求中和它相容的最后一个需求,记为pi。
* 若只在前i个需求中求相容子集,则可以得到的最大权值之和为M[i],
* 可以推导出:M[i]=max(wi+M[pi],M[i-1]),即如果最大的相容子集中包含需求i,则其权值之和为需求i的权值加上之前所有和它相容的需求子集的最大相容子集的权值之和;若不包含需求i,则其权值之和为前i-1个需求而的最大相容子集的权值之和。而应在其中取最大值,作为M[i]。
......@@ -19,7 +20,6 @@ public class 带权区域调度 {
public int start = -1;//起点
public int end = -1;//终点
public int weight = -1;//权重
public int p = -1;//求出所有需求前面所有的需求中和它相容的最后一个需求,记为pi
public Node(int start, int end, int weight) {
this.start = start;
......@@ -61,7 +61,14 @@ public class 带权区域调度 {
}
public static void main(String[] args) {
ArrayList<Node> nodes = new ArrayList<Node>();
nodes.add(new Node(0, 4, 2));
nodes.add(new Node(1, 6, 4));
nodes.add(new Node(5, 7, 4));
nodes.add(new Node(2, 9, 7));
nodes.add(new Node(8, 10, 2));
nodes.add(new Node(8, 11, 1));
ComputeP(nodes);
}
public static void ComputeP(ArrayList<Node> nodes) {
......@@ -72,16 +79,43 @@ public class 带权区域调度 {
return o1.start - o2.start;
return o1.end - o2.end;
}
});
for (int i = 0; i < nodes.size(); i++) {
for (Node node : nodes) {
if (node.start >= nodes.get(i).end)
node.p = i;
});//对所有的需求按照结束时间升序排序。
int[] p = new int[nodes.size()];
Arrays.fill(p, -1);
for (int i = 1; i < nodes.size(); i++) {//先选中一个区间
for (int j = i - 1; j >= 0; j--) {//从后往前找前面所有的需求中和它相容的最后一个需求
if (nodes.get(j).end <= nodes.get(i).start) {
p[i] = j;
break;
}
}
}
}//求出所有需求前面所有的需求中和它相容的最后一个需求,记为pi。
System.out.println(Arrays.toString(p));
int[] temp = new int[nodes.size()];
Arrays.fill(temp, -1);
// for (int i = 0; i < nodes.size(); i++) {
// for (int j = 0; j < nodes.size(); j++) {
// if (nodes.get(j).start >= nodes.get(i).end) {
// p[j] = i;
// nodes.get(j).p = i;
// }
// }
// }
int[] dp = new int[nodes.size()];
dp[0] = nodes.get(0).weight;
for (int i = 1; i < nodes.size(); i++) {
if (p[i] == -1) {
dp[i] = nodes.get(i).weight;
continue;
}
if (dp[p[i]] + nodes.get(i).weight > dp[i - 1]) {
dp[i] = dp[p[i]] + nodes.get(i).weight;
} else {
dp[i] = dp[i - 1];
}
}
System.out.println(Arrays.toString(dp));
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import java.util.Collections;
import java.util.Comparator;
/**
* poj 2376
* 有n头牛,它们都有一个工作时间的区间s至e,
* 给定一个总的工作时间t,
* 问最少需要多少头牛才能覆盖从1到t的工作时间
......@@ -12,6 +13,14 @@ import java.util.Comparator;
* 题目说人话就是:比如1点到10点需要有牛耕地,会给出,几点到几点需要工作
* 有的牛只在3点到4点工作,会给出每头牛在什么时间会工作
* 问最少需要多少头牛,才能在1-10点都有牛工作
*
* 排序+贪心
* 二、思路:简单的区间贪心。首先将牛的工作时间按起始时间最小(第一优先级升序)
* 结束时间最大的顺序(第二优先级升序)进行排序,然后取第n头牛时,
* 要满足以下条件:
* 1、第n头牛的s要小于等于第n-1头牛的e+1(这里要注意题目里给的是时间点,不是区间段)
* 2、第n头牛的e尽可能的大。之后就得考虑一些特例情况就可以了。
* 非常重要,细节记不住...以后再看
*/
public class 区间覆盖 {
static class Node {
......@@ -69,10 +78,15 @@ public class 区间覆盖 {
public static void main(String[] args) {
ArrayList<Node> list = new ArrayList<Node>();
list.add(new Node(1, 7));
list.add(new Node(3, 6));
list.add(new Node(6, 10));
F(list, list.size(), 0, 10);
// list.add(new Node(1, 7));
// list.add(new Node(3, 6));
// list.add(new Node(6, 10));
list.add(new Node(21, 50));
list.add(new Node(50, 81));
list.add(new Node(1, 20));
list.add(new Node(80, 99));
F(list, list.size(), 1, 99);
}
/**
......@@ -98,7 +112,7 @@ public class 区间覆盖 {
int s = list.get(i).start;
int e = list.get(i).end;
if (i == 0 && s > begin) break;//由于待选区间已经按开始时间排了序,
// 如果第一个找不到需要被覆盖的区间左边界,则无解
// 所以如果第一个找不到需要被覆盖的区间左边界,则无解
if (s <= start) {
end = Math.max(e, end);
} else {//开始下一个区间,超过end
......@@ -110,6 +124,7 @@ public class 区间覆盖 {
break;//无法完全覆盖给定的区间,无解
}
}
if (end >= last) {
break;//如果找出来一个区间,可以覆盖区间的全部,那么就够了,不需要找了
}
......
package Greedy;
import java.util.Arrays;
/**
* 有n根棍子,棍子长度为ai,从中选出周长尽可能长的三角形,请输出最大周长,
* 无法组成三角形则输出0
*/
public class 三角形 {
public static void main(String[] args) {
int[] arr = {2, 3, 4, 5, 6, 11, 10};
System.out.println(San(arr, arr.length));
}
/**
* @param arr 每根棍子的长度
* @param n 一共有n根棍子
* @return 最终三角形的周长
* 两边之和大于第三边,便符合三角形的定义
*/
public static int San(int[] arr, int n) {
Arrays.sort(arr);//排序使其符合贪心策略
int ans = 0;
for (int i = n - 1; i >= 2; i--) {
if (arr[i] < arr[i - 1] + arr[i - 2]) {
ans = arr[i] + arr[i - 1] + arr[i - 2];
//两边之和大于第三边,便符合三角形的定义
break;
}
}
return ans;
}
}
package Think;
import static java.lang.Math.max;
import static java.lang.Math.min;
/**
* poj 1852
* 有n只蚂蚁在木棍上爬行,每只蚂蚁的速度都是每秒1单位长度,
* 现在给你所有蚂蚁初始的位置(蚂蚁运动方向未定),
* 蚂蚁相遇会掉头反向运动,让你求出所有蚂蚁都掉下木棍的最短时间和最长时间。
* 解题思路:
* 因为蚂蚁都是一样的,所以当两只蚂蚁相遇时转向跟没转向没什么区别,
* 因为每只蚂蚁都会继承另一只蚂蚁的方向,所以可以视为蚂蚁方向不变,
* 所以最短时间就是所有蚂蚁距端点最近距离的最大值,
* 最长时间就是所有蚂蚁距端点最远距离的最大值。
*/
public class 蚂蚁 {
public static void main(String[] args) {
int[] arr = {2, 6, 7};
Ants(10, 3, arr);
}
/**
* @param L 木棍长度
* @param n 有n只蚂蚁
* @param arr 每只蚂蚁距离木棍左端的距离
*/
public static void Ants(int L, int n, int[] arr) {
int minT = 0;
int maxT = -1;
for (int i = 0; i < n; i++) {
maxT = max(max(arr[i], L - arr[i]), maxT);
minT = max(min(arr[i], L - arr[i]), minT);
}
System.out.println(minT);
System.out.println(maxT);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册