提交 5b317d43 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 be6f977a
package basic.queue;
import java.io.*;
import java.util.LinkedList;
import java.util.StringTokenizer;
import static java.lang.System.in;
/**
* https://www.acwing.com/problem/content/156/
* 给定一个大小为n≤106
......@@ -42,8 +48,73 @@ package basic.queue;
* 也就是下标小,存的值大,不选,因为起码都有2个
*/
public class 单调队列 {
public static void main(String[] args) {
public static void main(String[] args) throws IOException {
n = nextInt();
k = nextInt();
for (int i = 0; i < n; i++) {
a[i] = nextInt();
}
List();
// int head = 0, end = -1;
// for (int i = 0; i < n; i++) {
// if (head <= end && q[head] < i - k + 1) head++;
// //队列里面的元素不在窗口内,就删除该元素
// //i-k+1是当前窗口的第一个值的下标
// while (head <= end && a[q[end]] >= a[i]) end--;
// //如果队列尾部的值大于新加进来的值,就删除队尾元素,
// //对应的是队尾指针前移
// q[++end] = i;
// //把新元素插入到队尾
// if (i >= k - 1) System.out.println(a[q[head]]);
// }
}
//链表实现队列
static void List() throws IOException {
for (int i = 0; i < n; i++) {
if (!queue.isEmpty() && a[queue.peekFirst()] < i - k + 1) queue.removeFirst();
while (!queue.isEmpty() && a[queue.peekLast()] > a[i]) queue.removeLast();
queue.add(i);
if (!queue.isEmpty() && i >= k - 1) bw.write(a[queue.peekFirst()] + " ");
}
bw.write("\n");
queue.clear();
for (int i = 0; i < n; i++) {
if (!queue.isEmpty() && queue.peekFirst() < i - k + 1) queue.removeFirst();
while (!queue.isEmpty() && a[queue.peekLast()] <= a[i]) queue.removeLast();
queue.add(i);
if (i >= k - 1 && !queue.isEmpty()) bw.write(a[queue.peekFirst()] + " ");
}
bw.flush();
}
static int[] a = new int[(int) (1e6 + 10)];
static int[] q = new int[(int) (1e6 + 10)];
static int n, k;
static LinkedList<Integer> queue = new LinkedList<Integer>();
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());
}
}
package basic.two;
import java.util.TreeSet;
public class 二分模板 {
public static void main(String[] args) {
TreeSet<Integer> a = new TreeSet<Integer>();
a.add(5);
a.add(4);
a.add(6);
System.out.println(a);
}
static int bsearch(int l, int r) {
......
......@@ -10,30 +10,36 @@ public class 激光炸弹 {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
r = sc.nextInt();
int x, y, w;
N = r;
M = r;
int x, y, v;
while (n-- != 0) {
x = sc.nextInt();
y = sc.nextInt();
w = sc.nextInt();
a[++x][++y] += w;
v = sc.nextInt();
x++;
y++;
N = Math.max(N, x);//求出矩形最大长宽
M = Math.max(M, y);
qzh[x][y] += v;
}
for (int i = 1; i <= 5000; i++) {
for (int j = 1; j <= 5000; j++) {
qzh[i][j] += qzh[i - 1][j] + qzh[i][j - 1] - qzh[i - 1][j - 1] + a[i][j];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
qzh[i][j] += qzh[i - 1][j] + qzh[i][j - 1] - qzh[i - 1][j - 1];
}
}
}//前缀和
long res = 0;
for (int i = 1; i <= 5000 - r + 1; i++) {
for (int j = 1; j <= 5000 - r + 1; j++) {
res = Math.max(get(i, j, i + r - 1, j + r - 1), res);
for (int i = r; i <= N; i++) {
for (int j = r; j <= M; j++) {
res = Math.max(get(i - r + 1, j - r + 1, i, j), res);
}
}
//求出最大r-1的矩形
System.out.println(res);
}
static int n, r;
static int[][] qzh = new int[5005][5005];
static int[][] a = new int[5005][5005];
static int[][] qzh = new int[5010][5010];
static int n, r, N, M;
static int get(int x1, int y1, int x2, int y2) {
return qzh[x2][y2] - qzh[x1 - 1][y2] - qzh[x2][y1 - 1] + qzh[x1 - 1][y1 - 1];
......
......@@ -21,8 +21,7 @@ public class 拦截导弹 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
arr[N] = sc.nextInt();
N++;
arr[N++] = sc.nextInt();
}
int ans = 0;
for (int i = 0; i < N; i++) {
......
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 宠物小精灵之收服
* 总时间限制: 1000ms 内存限制: 65536kB
* 描述
* 宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。
* <p>
* 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,
* 野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。
* 我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。
* 小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。
* 现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?
* 输入
* 输入数据的第一行包含三个整数:N(0 < N < 1000),M(0 < M < 500),K(0 < K < 100),分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。
* 之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的伤害。
* 输出
* 输出为一行,包含两个整数:C,R,分别表示最多收服C个小精灵,以及收服C个小精灵时皮卡丘的剩余体力值最多为R。
* 样例输入
* 样例输入1:
* 10 100 5
* 7 10
* 2 40
* 2 50
* 1 20
* 4 20
* <p>
* 样例输入2:
* 10 100 5
* 8 110
* 12 10
* 20 10
* 5 200
* 1 110
* 样例输出
* 样例输出1:
* 3 30
* <p>
* 样例输出2:
* 0 100
* 提示
* 对于样例输入1:小智选择:(7,10) (2,40) (1,20) 这样小智一共收服了3个小精灵,皮卡丘受到了70点伤害,剩余100-70=30点体力。所以输出3 30
* 对于样例输入2:小智一个小精灵都没法收服,皮卡丘也不会收到任何伤害,所以输出0 100
* <p>
* 问题转化:
* 明显,精灵球和体力都是开销,而每个小精灵对应的价值都为1(只),所以这是一个二维费用背包问题。转化过来就是在使用n个精灵球且总价值最大时,R取最大值的情况。
* 一维背包只花费背包的体积
* 这个二维背包,
* 花费:精灵球数量和皮卡丘体力值
* 需要花两个东西
* 价值:小精灵的数量
* 属性是max
* 状态定义:f[i,j,k]表示为:所有只从前i种物品种选,
* 且花费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] )
* 最多收服的小精灵数量:f[K,N,M]
* 最少耗费体力怎么计算呢:f[K,N,m]==f[K,N,M]
* 其实是01背包问题可以三维优化二维
*/
public class 二维费用背包收服小精灵 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
v1[i] = sc.nextInt();
v2[i] = sc.nextInt();
}
two();
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= N; j++) {
for (int k = 0; k < M; k++) {
dp[i][j][k] = dp[i - 1][j][k];
if (j >= v1[i] && k >= v2[i]) {
dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j - v1[i]][k - v2[i]] + 1);
}
}
}
}
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--;
System.out.println(M - k);
}
static void two() {
for (int i = 1; i <= n; i++) {
for (int j = N; j >= v1[i]; j--) {
for (int k = M-1; k >= v2[i]; k--) {
f[j][k] = Math.max(f[j - v1[i]][k - v2[i]] + 1, f[j][k]);
}
}
}
System.out.println(f[N][M-1]);
//因为
int k = M-1;
while (k > 0 && f[N][k-1] == f[N][M-1]) k--;
System.out.println(M - k);
}
static int N, M, n;
static int[] v1 = new int[1000], v2 = new int[1000];
static int[][][] dp = new int[110][1010][510];
static int[][] f = new int[1010][510];
}
package 线性dp.背包模型;
//有1分2分3分的硬币,把钱N换成零钱有多少种兑换方法,n<3w
/**
* 有1分2分3分的硬币,把钱N换成零钱有多少种兑换方法,n<3w
* 状态定义:f[i,j],集合:所有只从前i个物品选,且恰好总体积是j的方案总和
* 属性:count
* 状态划分:包含第i个,不包含第i个
* 状态计算:不包含第i个->f[i-1,j]
* 包含第i个->f[i,j-v[i]]
* 状态合并:
* 所以f[i,j]=f[i-1,j]+f[i,j-v[i]]
* 当然后者要合法
* 显然:与数字组合题目不同的是,数字组合给定的数字,每一个只能选一次,01背包
* 这道题,是完全背包问题,每个数字可以选多次
* 恰好状态定义吻合
*/
public class 兑换硬币 {
public static void main(String[] args) {
System.out.println(one(2934));
System.out.println(two(2934));
}
static int N = 3;
static int[][] dp = new int[3][100];
static int[] w = {1, 2, 3};
static int[] v = {1, 2, 3};
static int[][] dp = new int[4][33333];
static int[] A = {1, 1, 2, 3};
static void ad() {
static int two(int size) {
dp[0][0] = 1;
for (int i = 1; i <= 3; i++) {
for (int j = 0; j <= size; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= A[i])
dp[i][j] += dp[i][j - A[i]];
}
}
return dp[3][size];
}
static int[] f = new int[333333];
static int one(int n) {
f[0] = 1;
for (int i = 1; i <= 3; i++) {
for (int j = i; j <= n; j++) {
f[j] += f[j - i];
}
}
return f[n];
}
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 如果我们有面值为1元、3元和5元的硬币若干枚,
* 如何用最少的硬币凑够11元? (表面上这道题可以用贪心算法,
* 但贪心算法无法保证可以求出解,比如1元换成2元的时候)
* 状态定义:f[i][j]表示为,前面i中硬币可选,j元最少可以用多少枚硬币表示
* 属性:min
* 状态划分:不选第i种硬币 f[i-1,j],选1个f[i-1,j-v[i]]+1,选2个f[i-1,j-2*v[i]]+2 ,选3个...
* 不失一般性选k个,f[i-1,j-k*v[i]]+k
* 求min
* 没想到吧,又是完全背包问题,哈哈哈哈哈
* 优化成1维
*/
public class 凑硬币 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
M = sc.nextInt();
for (int i = 1; i <= n; i++) {
v[i] = sc.nextInt();
}
System.out.println(one());
for (int i = 0; i <= M; i++) {
f[1][i] = i % v[1] == 0 ? i / v[1] : i / v[1] + 1;
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= M; j++) {
f[i][j] = f[i - 1][j];
for (int k = 0; k * v[i] <= j; k++) {
f[i][j] = Math.min(f[i - 1][j - k * v[i]] + k, f[i][j]);
}
}
}
System.out.println(f[n][M]);
}
static int one() {
for (int i = 0; i <= M; i++) {
dp[i] = i % v[1] == 0 ? i / v[1] : i / v[1] + 1;
}
for (int i = 2; i <= n; i++) {
for (int j = v[i]; j <= M; j++) {
dp[j] = Math.min(dp[j - v[i]] + 1, dp[j]);
}
}
return dp[M];
}
static int[] dp = new int[13];
static int[] v = new int[20];
static int[][] f = new int[20][13];
static int n, M;//n种硬币,M元
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 有N组物品,每个组只能选1个,
* 求最大价值
* 转换成01背包问题,
* 状态定义为f[i,j]:前i组物品可选,体积不超过j的所有选法最大值
* 状态划分:选第i组物品的第1个,选第i组物品的第2个,选第i组物品的第s[i]个,,不选第i组物品
* 状态计算:显然不选第i组物品就是f[i-1,j]
* |________|+w[i][1]
* |________|+w[i][2]
* ....
* |________|+w[i][k]
* 前面的最大值如何计算
* 前面的可以取的范围i-1组的物品,要选第i组的第k个物品,就要腾出来这么多
* 那么结合状态定义,最大价值就是:f[i-1,j-v[i][k]]+w[i][k]
* 选第i组物品的计算:选第i组物品的第k个,显然就是f[i-1,j-v[i][k]]+w[i][k]
* 空间复杂度可以优化成1维,最后还是O(n^2LogN)
*/
public class 分组背包问题 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
V = sc.nextInt();
int t;
for (int i = 1; i <= n; i++) {//n组
s[i] = sc.nextInt();//每一组有t个
for (int j = 0; j < s[i]; j++) {
v[i][j] = sc.nextInt();
//第i组,第j个
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++) {
if (v[i][k] <= j) {
//可以选第i组,第k个值
dp[j] = Math.max(dp[j - v[i][k]] + w[i][k], dp[j]);
}
}
}
}
System.out.println(dp[V]);
}
static int[] s = new int[105];
static int[][] v = new int[104][105];
static int[][] w = new int[104][105];
static int[] dp = new int[105];
static int n, V;
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 完全背包变形多重背包:每样物品最多选s[i]个
* 同理状态定义:f[i,j]代表体积为j前i个物品可选的最大价值
* 状态划分:选0个第i个物品,选1个第i个物品,选2个第i个物品,选3个第i个物品....选s[i]个第i个物品
* 状态计算,不失一般性,选k个:f[i-1,j-k*v[i]]+w[i] 只有在j>=k*v[i]并且k<=s[i]的时候才合法
*/
public class 多重背包1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
V = sc.nextInt();
for (int i = 1; i <= N; i++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
s[i] = sc.nextInt();
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
for (int k = 0; k <= s[i] && j >= k * v[i]; k++) {
dp[i][j] = Math.max(dp[i - 1][j - k * v[i]] + k * w[i], dp[i][j]);
}
}
}
System.out.println(dp[N][V]);
}
static int[][] dp = new int[105][105];
static int[] s = new int[105], w = new int[105], v = new int[105];
static int N, V;
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 多重背包转化为01背包问题
* 比如s[i]为10
* 转化为二进制,1,2,4和为7还剩3个
* 那么转化为,1,2,3,4
* 选5个答案就是1和4
* 选6个是4和2
* 选7个是4和3
* 选8个是4,3,1
* 选9个是4,3,2
* 选10个就是四个全部选
* 这样涵盖所有选择方案,每个就是选和不选的问题
*/
public class 多重背包二进制优化 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
V = sc.nextInt();
int a, b, c;
for (int i = 1; i <= N; i++) {
a = sc.nextInt();
b = sc.nextInt();
c = sc.nextInt();
int k = 1;
while (k <= c) {
cnt++;
v[cnt] = k * a;
w[cnt] = k * b;
c -= k;
k *= 2;
}
if (c > 0) {
cnt++;
v[cnt] = a * c;
w[cnt] = b * c;
}
}
N = cnt;//二进制优化后,一共有n个物品,01背包
for (int i = 1; i <= N; i++) {
for (int j = V; j >= v[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
}
}
System.out.println(dp[V]);
}
static int cnt;
static int dp[] = new int[2010];
static int[] v = new int[1000 * 13], w = new int[1000 * 13];
static int N, V;
}
package 线性dp.背包模型;
/**
* 与完全背包不同的是每个物品最多选s[i]个
* 状态定义:f[i,j]前i个物品可选,体积最大为j的最大价值
* 状态划分:选第i组物品的第1个,选第i组物品的第2个,选第i组物品的第s[i]个,和不选第i组物品
* 状态计算:显然不选第i组物品就是f[i-1,j]
* |________|+w[i][1]
* |________|+w[i][2]
* ....
* |________|+w[i][k]
* 前面的最大值如何计算
* 前面的可以取的范围i-1组的物品,要选第i组的第k个物品,就要腾出来这么多
* 那么结合状态定义,最大价值就是:f[i-1,j-v[i][k]]+w[i][k]
* 选第i组物品的计算:选第i组物品的第k个,显然就是f[i-1,j-v[i][k]]+w[i][k]
*/
public class 多重背包单调队列优化 {
public static void main(String[] args) {
}
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 给定N个正整数A1,A2,…,AN
* 从中选出若干个数,使它们的和为M,求有多少种选择方案。
* 输入格式
* 第一行包含两个整数N和M。
* 第二行包含N个整数,表示A1,A2,…,AN
* 输出格式
* 包含一个整数,表示可选方案数。
* 数据范围
* 1≤N≤100
* 1≤M≤10000,
* 1≤Ai≤1000
* 输入样例:
* 4 4
* 1 1 2 2
* 输出样例:
* 3
* M看做背包容量,每一个数看作物品,把Ai看做体积
* 求出总体积为M的所有方案数量
* 状态定义:f[i,j],集合:所有只从前i个物品选,且恰好总体积是j的方案总和
* 属性:count
* 状态划分:包含第i个,不包含第i个
* 状态计算:不包含第i个->f[i-1,j]
* 包含第i个->f[i-1,j-v[i]]
* 状态合并:
* 所以f[i,j]=f[i-1,j]+f[i-1,j-v[i]]
*/
public class 数字组合 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= n; i++) {
A[i] = sc.nextInt();
}
// one();
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
f[i][j] = f[i - 1][j];
if (j >= A[i])
f[i][j] += f[i - 1][j - A[i]];
}
}
System.out.println(f[n][m]);
//二维做法
}
static void one() {
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= A[i]; j--) {
dp[j] += dp[j - A[i]];
}
}
System.out.println(dp[m]);
}
static int[] A = new int[110];
static int[][] f = new int[110][10010];
static int[] dp = new int[10010];
static int n, m;
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 有 N
* 件物品和一个容量是 V 的背包,背包能承受的最大重量是 M
* 每件物品只能用一次。体积是 vi
* ,重量是 mi,价值是 wi
* 求解将哪些物品装入背包,可使物品总体积不超过背包容量,总重量不超过背包可承受的最大重量,且价值总和最大。
* 输出最大价值。
* 输入格式
* 第一行两个整数,N,V, M
* ,用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。
* 接下来有 N
* 行,每行三个整数 vi,mi,wi,用空格隔开,分别表示第 i
* 件物品的体积、重量和价值。
* 输出格式
* 输出一个整数,表示最大价值。
* 数据范围
* 0<N≤1000
* 0<V,M≤100
* 0<vi,mi≤100
* 0<wi≤1000
* 输入样例
* 4 5 6
* 1 2 3
* 2 4 4
* 3 4 5
* 4 5 6
* 输出样例:
* 8
* 分析:背包有重量和体积限制,每个物品可选可不选,求最大价值
* 状态表示:f[i,j,k] 所有只从前i种物品选,总体积超过j,总重量不超过k的选法
* 属性: max 最大价值
* 状态划分:所有包含第i个物品的选法,所有不包含物品i的选法
* 不选第i个物品:f[i-1,j,k]
* 包含第i个物品:f[i-1,j-v[i],k-m[i]]]+w[i
* |_______| + 物品i
* |_______| + 物品i
* |_______| + 物品i
* ...
* |_______| + 物品i
* 左边的最大值,选择范围是i-1,选上物品i合法,起码有j-v[i]的体积,k-m[i]的重量
* 所以包含第i个物品:f[i-1,j-v[i],k-m[i]]+w[i]
*/
public class 普通二维费用背包 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
V = sc.nextInt();
M = sc.nextInt();
for (int i = 1; i <= N; i++) {
v[i] = sc.nextInt();
m[i] = sc.nextInt();
w[i] = sc.nextInt();
}
System.out.println(two());
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
for (int k = 0; k <= M; k++) {
f[i][j][k] = f[i - 1][j][k];
if (j >= v[i] && k >= m[i]) {
f[i][j][k] = Math.max(f[i - 1][j - v[i]][k - m[i]] + w[i], f[i][j][k]);
}
}
}
}
System.out.println(f[N][V][M]);
}
static int two() {
for (int i = 1; i <= N; i++) {
for (int j = V; j >= v[i]; j--) {
for (int k = M; k >= m[i]; k--) {
dp[j][k] = Math.max(dp[j - v[i]][k - m[i]] + w[i], dp[j][k]);
}
}
}
return dp[V][M];
}
static int[] v = new int[1010], w = new int[1010], m = new int[1010];
static int N, V, M;
static int[][][] f = new int[1010][110][110];
static int[][] dp = new int[110][110];
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 有 N 种物品和一个容量是 V的背包。
* 物品一共有三类:
* 第一类物品只能用1次(01背包);
* 第二类物品可以用无限次(完全背包);
* 第三类物品最多只能用 s[i]次(多重背包)
* 每种体积是 v[i],价值是 w[i]
* 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,
* 且价值总和最大。
* 输出最大价值。
*/
public class 混合背包 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
V = sc.nextInt();
for (int i = 0; i < N; i++) {
}
}
static int N, V;
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 潜水员为了潜水要使用特殊的装备。
* 他有一个带2种气体的气缸:一个为氧气,一个为氮气。
* 让潜水员下潜的深度需要各种的数量的氧和氮。
* 潜水员有一定数量的气缸。每个气缸都有重量和气体容量。
* 潜水员为了完成他的工作需要特定数量的氧和氮。
* 他完成工作所需气缸的总重的最低限度的是多少?
* 例如:潜水员有5个气缸。每行三个数字为:
* 氧,氮的(升)量和气缸的重量:
* 3 36 120
* 10 25 129
* 5 50 250
* 1 45 130
* 4 20 119
* 如果潜水员需要5升的氧和60升的氮则总重最小为249(1,2或者4,5号气缸)。
* 你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。
* 第一行有2整数m,n(1≤m≤21,1≤n≤79)。它们表示氧,氮各自需要的量。
* 第二行为整数k(1≤n≤1000)表示气缸的个数。
* 此后的k行,每行包括ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3
* 整数。这些各自是:第i个气缸里的氧和氮的容量及汽缸重量。
* 【输出】
* 仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
* 【输入样例】
* 5 60
* 5
* 3 36 120
* 10 25 129
* 5 50 250
* 1 45 130
* 4 20 119
* 【输出样例】
* 249
* 显然三个东西,看如何划分:
* 物品: 氧气 氮气 重量
* a b c
* 费用1 费用2 价值最小
* >=m >=n
* 价值要求最低
* 费用1恰好是j,费用2恰好是k
* 状态定义改变:f[i,j,k]表示为:所有从前i种物品选,总氧气恰好是j,总氮气恰好是k的选法
* 属性:Min 最小重量
* 背包恰好和不超过,在初始化的时候有区别
* f[0,j,k]=在状态定义小于等于j,小于等于k的时候是合法的
* 在状态定义恰好是j,恰好是k的时候
* f[0,0,0]=0 是合法的
* f[0,j,k]=是非法的,因为只选0个不可能达到恰好是j,或者k
*/
public class 潜水员二维费用背包 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();//需要的氧气
m = sc.nextInt();//需要的氮气
shu = sc.nextInt();//有多少个气缸
for (int i = 1; i <= shu; i++) {
o[i] = sc.nextInt();
d[i] = sc.nextInt();
w[i] = sc.nextInt();
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
f[0][i][j] = Integer.MAX_VALUE - 1000;
}
}
f[0][0][0] = 0;
for (int i = 1; i <= shu; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= m; k++) {
f[i][j][k] = f[i - 1][j][k];
if (j >= o[i] && k >= d[i]) {
f[i][j][k]=Math.min(f[i-1][j-o[i]][k-d[i]]+w[i],f[i][j][k]);
}
}
}
}
System.out.println(f[shu][n][m]);
}
static int n, m, shu;
static int[] o = new int[1010], d = new int[1010], w = new int[1010];
static int[][][] f = new int[23][88][1010];
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
* 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
* 输入描述 Input Description
* 一个整数n,表示有n个物品
* 接下来n个整数,分别表示这n 个物品的各自体积
* 输出描述 Output Description
* 一个整数,表示箱子剩余空间。
* 样例输入 Sample Input
* 24
* 6
* 8
* 3
* 12
* 7
* 9
* 7
* 样例输出 Sample Output
* 0
* 弱01背包问题
* f[i,j]代表前i个物品可选,体积为j最多选的体积是多少
* 状态划分:选第i个物品,不选第i个物品
* 状态计算:不选的话显然就是f[i-1,j]
* 选的话,结合状态定义加上第i个物品的体积
* |________|+v
* 显然前面i的范围是i-1,能装下体积为v的物品的则是j-v
* 最终则是f[i-1,j-v]
* 求max ( f[i-1,j-v] ,f[i-1][j] )
* 结合01背包优化思路,优化成1维
*/
public class 装箱问题 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
V = sc.nextInt();
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
w[i] = sc.nextInt();
}
System.out.println(one());
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= V; j++) {
f[i][j] = Math.max(f[i - 1][j], f[i][j]);
if (j >= w[i])
f[i][j] = Math.max(f[i][j], f[i - 1][j - w[i]] + w[i]);
}
}
System.out.println(V - f[n][V]);
}
//优化成1维dp
static int one() {
for (int i = 1; i <= n; i++) {
for (int j = V; j >= w[i]; j--) {
dp[j] = Math.max(dp[j - w[i]] + w[i], dp[j]);
}
}
return V - dp[V];
}
static int[] dp = new int[20010];
static int[][] f = new int[35][20010];
static int[] w = new int[35];
static int n, V;
}
package 线性dp.背包模型;
import java.util.Scanner;
/**
* 01背包变种
* 时间映射体积,数量就是数量
*/
public class 采药 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
T = sc.nextInt();
M = sc.nextInt();
for (int i = 1; i <= M; i++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
for (int i = 1; i <= M; i++) {
for (int j = T; j >= v[i]; j--) {
f[j] = Math.max(f[j - v[i]] + w[i], f[j]);
}
}
System.out.println(f[T]);
}
static int[] w = new int[104], v = new int[105];
static int[] f = new int[1090];
static int T, M;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册