一、ACWing:数字三角形
(1)问题描述
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输入格式
第一行包含整数 nn,表示数字三角形的层数。
接下来 nn 行,每行包含若干整数,其中第 ii 行表示数字三角形第 ii 层包含的整数。
输出格式
输出一个整数,表示最大的路径数字和。
数据范围
1≤n≤5001≤n≤500,
−10000≤三角形中的整数≤10000−10000≤三角形中的整数≤10000
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
(2)代码实现
import java.util.Arrays;
import java.util.Scanner;
public class Main {
final int N = 510;
int INF = Integer.MIN_VALUE/2;
int n;
int[][] arr = new int[N][N];
int[][] f = new int[N][N];
void initialization() {
for (int[] k : f)
Arrays.fill(k, INF);
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
arr[i][j] = sc.nextInt();
}
}
}
int dp() {
for(int i = 1; i<=n; i++)
f[n][i] = arr[n][i];
for (int i = n-1; i >= 1; i--) {
for (int j = 1; j <= i; j++)
f[i][j] = Math.max(f[i+1][j+1]+arr[i][j], f[i+1][j]+arr[i][j]);//状态转移方程
}
return f[1][1];
}
public static void main(String[] args) {
Main s = new Main();
s.initialization();
int res = s.dp();
System.out.println(res);
}
}
二、 ACWing:分组背包问题
(1)问题描述
有 NN 组物品和一个容量是 VV 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 vijvij,价值是 wijwij,其中 ii 是组号,jj 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行有两个整数 N,VN,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 NN 组数据:
- 每组数据第一行有一个整数 SiSi,表示第 ii 个物品组的物品数量;
- 每组数据接下来有 SiSi 行,每行有两个整数 vij,wijvij,wij,用空格隔开,分别表示第 ii 个物品组的第 jj 个物品的体积和价值;
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000<N,V≤100
0<Si≤1000<Si≤100
0<vij,wij≤1000<vij,wij≤100
输入样例
3 5
2
1 2
2 4
1
3 4
1
4 5
输出样例:
8
(2)代码实现
import java.util.*;
public class Main{
static int N=110;
static int[][] v=new int[N][N];
static int[][] w=new int[N][N];
static int[] s=new int[N];
static int[] f=new int[N];
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int m=in.nextInt();
for(int i=1;i<=n;i++){
s[i]=in.nextInt();
for(int j=1;j<=s[i];j++){
v[i][j]=in.nextInt();
w[i][j]=in.nextInt();
}
}
for(int i=1;i<=n;i++){
for(int j=m;j>=0;j--){
for(int k=1;k<=s[i];k++){
if(v[i][k]<=j)
f[j]=Math.max(f[j],f[j-v[i][k]]+w[i][k]);
}
}
}
System.out.println(f[m]);
}
}
三、2020年蓝桥杯java省赛B组 :J 网络分析
(1)问题描述
小明正在做一个网络实验。
他设置了 n 台电脑,称为节点,用于收发和存储数据。
初始时,所有节点都是独立的,不存在任何连接。
小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信
了。两个节点如果存在网线连接,称为相邻。
小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送
到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接
或间接相邻的节点都收到了信息。所有发送和接收的节点都会将信息存储下来。
一条信息只存储一次。
给出小明连接和测试的过程,请计算出每个节点存储信息的大小。
输出一行,包含 n 个整数,相邻整数之间用一个空格分割,依次表示进行
完上述操作后节点 1 至节点 n 上存储信息的大小。
(2)代码实现
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
static int[] link, lazy, value;
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(System.out);
in.nextToken();
int n = (int)in.nval;
in.nextToken();
int m = (int)in.nval;
value = new int[n + 1];
lazy = new int[n + 1];
link = new int[n + 1];
for (int i = 1; i <= n; i++) link[i] = i;
while (m-- > 0) {
in.nextToken();
int i = (int)in.nval;
in.nextToken();
int v = (int)in.nval;
in.nextToken();
int w = (int)in.nval;
if (i == 1) {
v = find(v);
w = find(w);
if (v != w) {
link[v] = w;
lazy[v] = value[v] - value[w];
}
} else value[find(v)] += w;
}
for (int i = 1; i <= n; i++)
out.print((value[find(i)] + lazy[i]) + " ");
out.close();
}
static int find(int x) {
if (link[x] != x) {
int t = link[x];
link[x] = find(link[x]);
lazy[x] += lazy[t];
}
return link[x];
}
}