提交 498742be 编写于 作者: qq_36480062's avatar qq_36480062

c

上级 ddf3bb78
......@@ -8,12 +8,12 @@ package dp.背包模型;
* 属性:count
* 状态划分:不包含第i个,选了第i个物品1个,选了第i个物品2个,选了第i个物品3个...
* 状态计算:不包含第i个->f[i-1,j]
* 选了第i种物品k个->f[i,j-v[i]]
* 选了第i种物品k个->f[i,j-v[i]*k]
* |_____| + 0个i
* |_____| + 1个i
* ...
* 求取左边的和,加上右边的和
* 左边的方案选择:1~i-1中选择,不包含i的话体积应该是j-k*i
* 左边的方案选择:1~i-1中选择,不包含i的话体积应该是j-k*v[i]
* 则是:f[i-1,j-v[i]*k]
* 最终:f[i,j]=f[i-1,j]+f[i-1,j-v[i]*1]+f[i-1,j-v[i]*2]+...+f[i-1,j-v[i]*k]
* 易得f[i,j-v]= f[i-1,j-v[i]*1]+f[i-1,j-v[i]*2]+...+f[i-1,j-v[i]*k]
......
......@@ -7,12 +7,16 @@ import java.util.Scanner;
* 总时间限制: 1000ms 内存限制: 65536kB
* 描述
* 宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。
* <p>
* 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,
* 野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。
* 我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。
* 小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。
* 现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?
* 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。
* 然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,
* 野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,
* 小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。
* 我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,
* 那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。
* 小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,
* 小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。
* 现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。
* 请问,小智该如何选择收服哪些小精灵以达到他的目标呢?
* 输入
* 输入数据的第一行包含三个整数:N(0 < N < 1000),M(0 < M < 500),K(0 < K < 100),分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。
* 之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的伤害。
......@@ -56,7 +60,7 @@ import java.util.Scanner;
* 且花费1不超过j,花费2不超过k的选法的最大价值
* 状态计算:选第i个物品和不选第i个物品
* 不选第i个物品:f[i-1,j,k]选择范围变小,精灵球数量和体力值不变(体积不变)
* 选择第i个物品:max( f[i-1,j-v1[i],k-v2[i]+1] , f[i-1,j,k] )
* 选择第i个物品:max( f[i-1,j-v1[i],k-v2[i]]+1 , f[i-1,j,k] )
* 最多收服的小精灵数量:f[K,N,M]
* 最少耗费体力怎么计算呢:f[K,N,m]==f[K,N,M]
* 其实是01背包问题可以三维优化二维
......@@ -85,6 +89,7 @@ public class 二维费用背包收服小精灵 {
System.out.println(dp[n][N][M - 1]);
int k = M - 1;
while (k > 0 && dp[n][N][k - 1] == dp[n][N][M - 1]) k--;
//如果收付k个精灵,只花费M-1体力也行,或者M-2...下不封顶,找最小的那个花费,
System.out.println(M - k);
}
......
......@@ -4,9 +4,9 @@ package dp.背包模型;
* 有1分2分3分的硬币,把钱N换成零钱有多少种兑换方法,n<3w
* 状态定义:f[i,j],集合:所有只从前i个物品选,且恰好总体积是j的方案总和
* 属性:count
* 状态划分:包含第i个,选了第i个物品1个,选了第i个物品2个,选了第i个物品3个...
* 状态划分:包含第i个,选了第i个物品1个,选了第i个物品2个,选了第i个物品3个...
* 状态计算:不包含第i个->f[i-1,j]
* 选了第i种物品k个->f[i,j-v[i]]
* 选了第i种物品k个->f[i,j-v[i]*k]
* |_____| + 0个i
* |_____| + 1个i
* ...
......
......@@ -34,9 +34,9 @@ public class 分组背包问题 {
w[i][j] = sc.nextInt();
}
}
for (int i = 1; i <= n; i++) {
for (int j = V; j >= 0; j--) {
for (int k = 0; k < s[i]; k++) {
for (int i = 1; i <= n; i++) {//枚举每一组
for (int j = V; j >= 0; j--) {//枚举体积
for (int k = 0; k < s[i]; k++) {//枚举第i组
if (v[i][k] <= j) {
//可以选第i组,第k个值
dp[j] = Math.max(dp[j - v[i][k]] + w[i][k], dp[j]);
......
......@@ -23,7 +23,7 @@ public class 完全背包 {
static void O3() {
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
dp[i][j] = dp[i - 1][j];
dp[i][j] = dp[i - 1][j];//至少有前i-1种物品可选,容量为v的价值
if (j >= w[i])
dp[i][j] = Math.max(dp[i][j - w[i]] + v[i], dp[i][j]);
}
......@@ -33,10 +33,10 @@ public class 完全背包 {
static void O2() {
for (int i = 1; i <= N; i++) {
for (int j = w[i]; j <= V; j++) {
f[j] = Math.max(f[i], f[i - w[i]] + v[i]);
for (int j = v[i]; j <= V; j++) {
f[j] = Math.max(f[j], f[j - v[i]] + w[i]);
}
}
System.out.println(f[N]);
System.out.println(f[V]);
}
}
package graph;
import java.io.*;
import java.util.ArrayDeque;
import java.util.StringTokenizer;
import static java.lang.System.in;
/**
* lougu
* https://www.luogu.com.cn/problem/P1807
* 设 G为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,
* 请设计算法,计算图 G 中 <1,n>间的最长路径。
* 输入的第一行有两个整数,分别代表图的点数 nn 和边数 mm。
* <p>
* 第 2到第(m+1) 行,每行 3 个整数 u, v, w
* 代表存在一条从 u 到v 边权为 w 的边。
* 输出格
* 输出一行一个整数,代表 1 到 n 的最长路。
* 若 1与 n 不联通,请输出 −1。
* 输入输出样例
* 输入
* 2 1
* 1 2 1
* 输出
* 1
*/
public class 两点最长路 {
public static void main(String[] args) throws IOException {
n = nextInt();
m = nextInt();
int a, b, c;
h = new int[n + 10];
st = new boolean[n + 10];
dis = new int[n + 10];
e = new int[m + 10];
ne = new int[m + 10];
w = new int[m + 10];
for (int i = 0; i < m; i++) {
a = nextInt();
b = nextInt();
c = nextInt();
add(a, b, c);
}
ArrayDeque<Integer> q = new ArrayDeque<Integer>();
q.add(1);
st[1] = true;
while (!q.isEmpty()) {
a = q.poll();
st[a] = false;
for (int i = h[a]; i != 0; i = ne[i]) {
b = e[i];
if (dis[b] < dis[a] + w[i]) {
dis[b] = dis[a] + w[i];
if (!st[b]) {
q.add(b);
st[b] = true;
}
}
}
}
if (dis[n] == 0) System.out.println(-1);
else System.out.println(dis[n]);
}
static int n, m, N = 2040, M = (int) (5e4 + 10), ct = 1;
static boolean[] st;
static int[] dis;
static int[] h;
static int[] e;
static int[] w;
static int[] ne;
static void add(int a, int b, int c) {
e[ct] = b;
w[ct] = c;
ne[ct] = h[a];
h[a] = ct++;
}
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException {// 读取下一行字符串
return reader.readLine();
}
static String next() throws IOException {// 读取下一个字符串
while (!tokenizer.hasMoreTokens()) {
//如果没有字符了,就是下一个,使用空格拆分,
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {// 读取下一个int型数值
return Integer.parseInt(next());
}
static double nextDouble() throws IOException {// 读取下一个double型数值
return Double.parseDouble(next());
}
}
......@@ -8,7 +8,8 @@ import java.util.StringTokenizer;
import static java.lang.System.in;
/**
* 不知道为啥有一个过不了,洛谷数据错了...
* 从1开始到达,不能用那个模板!!!
* 我错了,洛谷都不会错
*/
public class 洛谷负环 {
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
......@@ -41,7 +42,6 @@ public class 洛谷负环 {
cnt = 1;
n = nextInt();
m = nextInt();
Arrays.fill(dis, 0);
Arrays.fill(he, 0);
Arrays.fill(ne, 0);
Arrays.fill(count, 0);
......@@ -61,10 +61,12 @@ public class 洛谷负环 {
}
private static boolean spfa() {
for (int i = 1; i <= n; i++) {
q.add(i);
vis[i] = true;
}
Arrays.fill(vis, false);
q.clear();
Arrays.fill(dis, Integer.MAX_VALUE / 2);
q.add(1);
dis[1] = 0;
vis[1] = true;
int t = 0;
while (!q.isEmpty()) {
int v = q.poll();
......@@ -85,15 +87,15 @@ public class 洛谷负环 {
return false;
}
static boolean[] vis = new boolean[2005];
static ArrayDeque<Integer> q = new ArrayDeque<Integer>();
static int[] count = new int[2005];
static int[] dis = new int[2005];
static boolean[] vis = new boolean[6005];
static int[] count = new int[6005];
static int[] dis = new int[6005];
static int t, n, m, cnt = 1;
static int[] he = new int[2005];
static int[] ne = new int[10005];
static int[] e = new int[10005];
static int[] w = new int[10005];
static int[] he = new int[6005];
static int[] ne = new int[6005];
static int[] e = new int[6005];
static int[] w = new int[6005];
static void add(int a, int b, int c) {
e[cnt] = b;
......
......@@ -28,6 +28,7 @@ import static java.lang.System.in;
* 排列型枚举,n个数,有n个坑,第一个坑有n种选择,第二个坑有n-1中选择,第n个坑只有一种选择
* 第一个坑的n种选择,是平行的,
* 交换性枚举每一位,是效率最高的
* 全排列
*/
public class 排列枚举 {
public static void main(String[] args) {
......
......@@ -26,6 +26,7 @@ package 递归;
* 2 3 5
* 2 4 5
* 3 4 5
* 随机选m个不考虑顺序
*/
public class 组合m个数 {
public static void main(String[] args) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册