提交 0e3d2209 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 f4580c66
package com.shiyu;
import java.util.PriorityQueue;
public class tsdt {
public static void main(String[] args) {
System.out.println(isPalindrome(121));
PriorityQueue<Integer> a = new PriorityQueue<Integer>();
a.add(6);
a.add(5);
System.out.println(a.poll());
// System.out.println(isPalindrome(121));
// PriorityQueue<Integer> a = new PriorityQueue<Integer>();
//
// a.add(6);
// a.add(5);
//
// System.out.println(a.poll());
int d=2&3;
System.out.println(d);
}
......
package dp;
import java.util.*;
/**
* 带权的区间调度
* 存在单一资源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]。
* 计算出来所有的M[i]之后,自顶而上,求出所有使权值之和变为最大的需求。
*/
public class 带权区域调度 {
static class Node implements Comparator<Node> {
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;
this.end = end;
this.weight = weight;
}
@Override
public int compare(Node o1, Node o2) {
if (o1.end == o2.end)
return o1.start - o2.start;
return o1.end - o2.end;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return start == node.start &&
end == node.end &&
weight == node.weight;
}
@Override
public int hashCode() {
return start * 100 + end * 10 + weight;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Node{");
sb.append("start=").append(start);
sb.append(", end=").append(end);
sb.append(", num=").append(weight);
sb.append('}');
return sb.toString();
}
}
public static void main(String[] args) {
}
public static void ComputeP(ArrayList<Node> nodes) {
Collections.sort(nodes, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if (o1.end == o2.end)
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[] temp = new int[nodes.size()];
Arrays.fill(temp, -1);
}
}
}
\ No newline at end of file
package greedy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* 有n头牛,它们都有一个工作时间的区间s至e,
* 给定一个总的工作时间t,
* 问最少需要多少头牛才能覆盖从1到t的工作时间
* <p>
* 题目说人话就是:比如1点到10点需要有牛耕地,会给出,几点到几点需要工作
* 有的牛只在3点到4点工作,会给出每头牛在什么时间会工作
* 问最少需要多少头牛,才能在1-10点都有牛工作
*/
public class 区间覆盖 {
static class Node {
public int start;
public int start = -1;
public int end = -1;
public Node(int start) {
......@@ -55,10 +68,57 @@ 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);
}
public static void F() {
/**
* @param list 区间对象
* @param N 区间数量
* @param begin 需要覆盖的区间开头,
* @param last 需要覆盖的区间结尾
*/
public static void F(ArrayList<Node> list, int N, int begin, int last) {
Collections.sort(list, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if (o1.start == o2.start)
return o1.end - o2.end;
return o1.start - o2.start;
}
});//按照区间左边界升序排列
int start = begin;//要覆盖的目标点
int end = 1;
int ans = 1;
for (int i = 0; i < N; i++) {
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
ans++;//上一个目标覆盖达成
start = end + 1;
if (s <= start) {
end = Math.max(end, e);
} else {
break;//无法完全覆盖给定的区间,无解
}
}
if (end >= last) {
break;//如果找出来一个区间,可以覆盖区间的全部,那么就够了,不需要找了
}
}
if (end < last) {
System.out.println(-1);
} else {
System.out.println(ans);
}
}
}
......@@ -23,7 +23,9 @@ import java.util.Comparator;
* 还有所有 0<i<=max_v的值构成的 i到i-1的长0的边和 i-1到i的长1的边.所以这样我们就形成了一个具有点[0,max_v]的有向图.在原图处理时,为了避免ai-1==-1,我们令所有ai与bi都自增了10.所以我们形成了一个具有点[9,max_v]的有向图(其实就是差分约束系统).我们的目标是令S[max_v]-S[9]的值最小.(切记这里不是仅使S[max_v]的值最小,因为我们这里只有从9 ,10,11,…max_v 的值构成了一个差分约束系统.max_v的值和0号点的值是不在一个系统的. 0号点是超级源点,它的值与系统中其他点的值是无关的.)
* 然后我们上面已经知道了希望让系统中S[max_v]和S[9]的值差距尽量小.(构成差分约束系统时,1.如果在所有点外添加一个超级源0号点,并使得超级源到所有其他点的距离为0,那么最终求出的0号点到其他所有原始点的最短距离就是本系统的一个可行解,且可行解之间的差距最小.      2.如果初始时不添加超级源,只是将原始点的初始距离设为INF,且令其中一个原始点的初始距离为0,然后求该点到其他所有点的最短距离,那么最短距离的集合就是一个可行解,且该可行解两两之间的差距最大.注意方案2只能在该问题一定存在解的时候即肯定不存在负权环的时候用.否则从1号点到其他点没有路,但是其他点的强连通分量中有负权环,这样根本探测不到错误) 所以我们需要采取方案1.
* 转自大佬:
* 贪心策略
* 贪心策略,尽量先选区间右边的点
* 还有树状数组
* 拆分约束
*/
public class 区间选点 {
static class Node {
......@@ -75,6 +77,8 @@ public class 区间选点 {
}
/**
* 贪心策略实现
*
* @param n 区间数量
* @param list 区间对象
*/
......@@ -94,24 +98,25 @@ public class 区间选点 {
for (int i = 0; i < n; i++) {
int start = list.get(i).start;
int end = list.get(i).end;
int cnt = sum(axis, start, end);
list.get(i).num -= cnt;
int cnt = sum(axis, start, end);//查询数轴上(数组start到end)这个范围已经存在的点,
list.get(i).num -= cnt;//当前该区间需要多少个点(去掉已经,已经包含数量的点)
while (list.get(i).num > 0) {
if (axis[end] == 0) {
axis[end] = 1;
list.get(i).num--;
end--;
if (axis[end] == 0) {//如果该区间右边界如果未被标记
axis[end] = 1;//标记区间右边界
list.get(i).num--;//维护该区间需要的点
end--;//维护end,右边界左移一位
} else {
end--;
end--;//右边界左移一位
}
}
}
System.out.println(sum(axis, 0, max));
return sum(axis, 0, max);
return sum(axis, 0, max);//整个数轴上有几个点
}
/**
* 统计数轴axis上s-t区间已经有多少个点被选中
* 贪心策略辅助统计方法
*
* @param axis 数轴
* @param s 区间左边界
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册