Fork me on GitHub

0-1背包问题

0-1背包问题

0-1背包问题是一个典型的动态规划问题

问题背景:用有限的背包容量去装价值最多的物品的组合,物品有质量和价值。

0-1背包问题是最简单的背包问题,对于一个物品,只有两种选择——装或者不装。因此这个程序不能使用贪心算法来解,使用动态规划来解。

因为背包问题是一个动态规划问题,它可能满足动态规划的三要素。

三要素:

最优子程序、最优值,最优解

背包问题的算法

当我们有了这些算法逻辑上的准备后,就可以着手实现算法了。

算法实现

对于0-1背包问题,我们逻辑上是从上到下进行添值的,但是在算法实现的过程中,我们是使用从低往上添值的。

自上而下的算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.dwx.passage3;

public class Knapsack {


/*
* n : 定义物品的数量
* c: 定义背包的容量
* w[]:定义我拼的重量
* v[]:定义每个物品的价值
* m[][]:定义记录表格*/
private int n;
private int c;
private int[] w;
private int[] v;
private int[][] m;

//我们写的是用来调用的方法,使用get/set方法体现我们方法的封装


public int getN() {
return n;
}

public void setN(int n) {
this.n = n;
}

public int getC() {
return c;
}

public void setC(int c) {
this.c = c;
}

public int[] getW() {
return w;
}

public void setW(int[] w) {
this.w = w;
}

public int[] getV() {
return v;
}

public void setV(int[] v) {
this.v = v;
}

public int[][] getM() {
return m;
}

public void setM(int[][] m) {
this.m = m;
}

//算法的主体
public void knapsack(){
//对我们的m矩阵机型初始化
int j,k,l;
//对于m[][]
//i表示是第几个物品,j表示容量为j的子背包
for (j=0;j<=c;j++){
//如果能够 对于子背包能够装下就装
if (j+1 >= w[n]){
m[n][j] = v[n];
}
//不能装就跳过
else
m[n][j] = 0;
}

//操作除了最后一行的其他行
for (int i = n-1;i>=1;i--){
for (j=0;j<=c;j++){
if (j>=w[i]){
m[i][j] = m[i+1][j]>m[i+1][j-w[i]]+v[i] ? m[i+1][j]:m[i+1][j-w[i]]+v[i];
}
}
}
}
}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import com.dwx.passage3.Knapsack;

public class KnapsackTest {
public static void main(String[] args) {
Knapsack knapsack = new Knapsack();
/*
* n : 定义物品的数量
* c: 定义背包的容量
* w[]:定义我拼的重量
* v[]:定义每个物品的价值
* m[][]:定义记录表格*/
int c = 4;
int n = 3;
int w[] = new int[]{4,3,1};
int v[] = new int[]{3000,2000,1500};
int m[][] = new int[3][4];
knapsack.setC(c-1);
knapsack.setM(m);
knapsack.setV(v);
knapsack.setW(w);
knapsack.setN(n-1);
//执行方法
knapsack.knapsack();

//获得执行后的m表格
//因为我们是从上到下填写的
int[][] m1 = knapsack.getM();
for (int[] ints : m1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}

输出:

1
2
3
0	0	0	0	
0 0 0 3500
1500 1500 1500 1500

自上而下的编写方式

选址问题

选址问题

选址问题是指为一个或者几个服务设置在一定区域内选定他的位置,是的某一指标达到最优值。选址问题根据这些设置需要的指标的要求可以大致分为两类:

  • 中心问题
  • 重心问题

中心问题

中心问题指的是一些紧急公共设施如医院、消防站的选址,要求网路中最远的被服务对象离服务站的距离尽可能小。‘因此我们可以使用Floyd算法求得每组两点之间的最短距离。在选择某一行最大值的与其他行进行比较。选择最大值的最小值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import com.dwx.passage2.Floyd;

import java.util.Scanner;

public class zhongxinwenrti {
public static void main(String[] args) {
//我们这边使用的是无向图
Scanner scanner = new Scanner(System.in);
int inf = 99999999;
//m 表示点数 n表示边数
int m = scanner.nextInt();
int n = scanner.nextInt();
int x, y;
double l;
//创建数组
double[][] a = new double[m][m];
//对数组初始化
int i, j;
for (i = 0; i < m; i++) {
for (j = 0; j < m; j++) {
if (i == j) {
a[i][j] = 0;
} else {
a[i][j] = inf;
}

}
}
//导入边数据
for (i = 1; i <= n; i++) {
//x表示横坐标 y表示纵坐标 l表示长度
x = scanner.nextInt();
y = scanner.nextInt();
l = scanner.nextDouble();
//这里我们使用的是无向图
a[x][y] = l;
a[y][x] = l;
}
for (double[] ints : a) {
for (double anInt : ints) {
if (anInt == inf) {
System.out.print("inf" + "\t");
} else {
System.out.print(anInt + " ");
}
}
System.out.println();
}

System.out.println("=====================");
//调用Floyd算法求得 两两点之间的最短路径
Floyd floyd = new Floyd();
floyd.setE(a);
floyd.floyd();
double[][] e = floyd.getE();

for (double[] ints1 : e) {
for (double anInt : ints1) {
if (anInt == inf) {
System.out.print("inf" + "\t");
} else {
System.out.print(anInt + " ");
}
}
System.out.println();
}
}
}


程序输出:

1
2
3
4
5
6
7
0.0    3.0    5.0    10.0    7.0    5.5    7.0    
3.0 0.0 2.0 7.0 4.0 2.5 4.0
5.0 2.0 0.0 5.0 2.0 4.5 6.0
10.0 7.0 5.0 0.0 3.0 7.0 8.5
7.0 4.0 2.0 3.0 0.0 4.0 5.5
5.5 2.5 4.5 7.0 4.0 0.0 1.5
7.0 4.0 6.0 8.5 5.5 1.5 0.0

可以看到 我们的最短路径矩阵,每一行的最大值中的最小值是在第3行 因此建设在V3点

重心问题

某些设备如工厂,学校,邮局等不是紧急单位,但是和民生息息相关的公共设置,需要选择要求到每个点的距离中的最短,才能保证有条件的公平与便利。

解题思路:利用弗洛伊德算法,求得两点之间最短距离的矩阵,获得矩阵的各行的参数的相加。找到最小的。

程序实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import com.dwx.passage2.Floyd;

import java.util.Scanner;

public class Zhongxinwenti {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int inf = 99999999;
//创建矩阵
int m = scanner.nextInt();
int n = scanner.nextInt();
double[][] a = new double[m][m];
//矩阵初始化
int i,j,k,x,y;
double l;
for (i=0;i<m;i++){
for (j=0;j<m;j++){
if (i==j){
a[i][j] = 0;
}else {
a[i][j] = inf;
}
}
}
//读入数据
for (i=1;i<=n;i++){
x = scanner.nextInt();
y = scanner.nextInt();
l = scanner.nextDouble();
a[x][y] = l;
a[y][x] = l;
}
//调用弗洛伊德算法求解
Floyd floyd = new Floyd();
floyd.setE(a);
floyd.floyd();
double[][] e = floyd.getE();
for (double[] doubles : e) {
for (double aDouble : doubles) {
System.out.print(aDouble+"\t");
}
System.out.println();
}
System.out.println("=========================================");
double sum = 0;
for (double[] doubles : e) {
sum = 0;
for (double aDouble : doubles) {
sum = sum + aDouble;
}
System.out.println(sum);
}


}
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0.0	3.0	5.0	8.0	7.0	7.0	8.5	
3.0 0.0 2.0 5.0 4.0 4.0 5.5
5.0 2.0 0.0 3.0 2.0 6.0 7.5
8.0 5.0 3.0 0.0 1.0 5.0 6.5
7.0 4.0 2.0 1.0 0.0 4.0 5.5
7.0 4.0 6.0 5.0 4.0 0.0 1.5
8.5 5.5 7.5 6.5 5.5 1.5 0.0
=========================================
38.5
23.5
25.5
28.5
23.5
27.5
35.0

Process finished with exit code 0

由此可知 建在v2或者v5都可以

监审网站的第二个编程阶段

了解了添加的原理 百年希尔过程

2022/3/3

获得了后端接口和数据库 需要写一个注册功能

2022/3/5

编写完了登录和注册功能 还实现了信息的验证消息(虽然是我拿同学写好的)

2022/3/6

后端实现了对公办封面的信息收取和展示(数据库插入和查询)

信息的收取已经和前端进行了交互

2022/3/9

前后端交互 使用JSONarray

2022/3/17

简单来说 添加程序已经写完了,后续是跟前端交互。

本身计划我就写添加,但是情况有变,现在我还要写数据查询

数据的查询时对于我来说十分简单的,但是对于前端 会有点痛苦

十万个数找到前十个

十万个数找到前十个

这是考研题中能够数据结构中的一道题,要求时间复杂度尽可能的小,因此我们使用简单排序或者是快速排序进行完全排序后输出前几个是完全不可以的,时间复杂的会很高,这里我选择使用线性选择的方式。

算法思路

使用线性选择 ,选择到第十个数据,因为线性选择是以快排为基础的,因此当我们找到了这第十个数据。那么我们此时生成的数组第十个数据前边的比他小,前十个就是在这个乱序中.

  • 先使用线性选择选择到第十个数据
  • 将这个数组的前十个数据进行排序(随意,可以使用简单排序)
  • 输出结果

验证,因为我们的数组是随机生成的 无法保证找到的数据是正确的(可能某个程序错误将数组更改),因此我们需要在生成数组的时候将数组存储到文件中,然后使用全排序对齐进行排序,之后输出前十个来验证是否和我们使用线性选择找到的数据相同。

程序实践

这里我们开一个文件把我们的随机生成的数组储存起来,以方便以后的验证使用,此时就需要用的文件的读取知识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import com.dwx.passage2.RandomizedSelect;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class fisrtTen {
public static void main(String[] args) throws IOException {
//成功一个有十万个数据的数组 用随机数产生
int[] a = new int[100000];
int length = a.length;
int i,j,k;

for (i=0;i<length;i++){
//产生10万个随机数
a[i] = (int)(Math.random()*1000000)+10000;
}
//我们可以将这个数组先存放到file中 到其他的程序进行测试
String fileName = "shiwan.txt";
File file = new File(fileName);
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(file);
} catch (IOException e) {
e.printStackTrace();
}
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.write(Integer.toString(a.length));
for (int i1 : a) {
writer.newLine();
writer.write(Integer.toString(i1));
}
writer.flush();
writer.close();

//选择前十个
//调用线性选择程序
RandomizedSelect select = new RandomizedSelect();
select.setList(a);
int i1 = select.RandomizedSelect(0, a.length - 1, 10);
System.out.println("第十个数据是:"+i1);
int[] list = select.getList();
//对前十个数据进行排序
simpleSort(list,0,9);
for (i=0;i<10;i++){
System.out.println(list[i]+"\t");
}
}

//我们这里需要一个简单排序
public static void simpleSort(int[] e,int start,int end){
int i;
int j;
int temp;
int k;
i = start;
for (i=start;i<=end;i++){
temp = e[i];
k = i;
for (j=i;j<=end;j++){
//寻找每次循环的最小值
if (e[j]<temp){
temp = e[j];
k = j;
}

}
//进行交换 把最小值放到合适的位置
e[k] = e[i];
e[i] = temp;
}
}
}


线性的算则:这里我是用的是随机选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.dwx.passage2;

public class RandomizedSelect {

//正常来说 我们操作的都是整数数组
private int list[];
//我们使用的是private私有对象 因此需要编写get/set方法来设置和获取值

public int[] getList() {
return list;
}

public void setList(int[] list) {
this.list = list;
}

//快速排序的思路是将第一个作为端点 但是我们这里使用一个随机数来获得端点
/*
参数表:
start:列表要查询的开始
end:列表查询的结束
find:我们要查询的第几小
*/

public int RandomizedSelect(int start,int end,int find){
//编写程序结束程序
//如果开始等于结束 我们没有什么课选的了 就选择到了合适的数据
if (start==end){
//这个就是我们找到的第几小的结果
return list[start];
}
int i = RandomQuickSort(start,end);
//比较我们得到的这个第几小和我们的目标小又什么区别
//如果i大 则说明我们要找的find在划分后的后边
//则将我们的起始地址设置为i+1,结束还是end,此时我们要找find-i小
//注意 我们这里的j 因为 我们的start 不一定就是从零开始的 因此 我们选择后的第几小 就需要用find-j
int j = i-start+1;
if (find<=j){
return RandomizedSelect(start,i,find);
}else {
return RandomizedSelect(i+1,end,find-j);
}
}


//这个程序是对我们需要的list的一段进行一次快排 二我们快排的结果是随机的 通过random来获得我们的基准元素
public int RandomQuickSort(int start,int end){
//我们这里只需要一个开始和一个结束
//获得一个随机数 在start和end之间
//我们这里的随机数要设置好
int n = (int)(Math.random()*100)%(end-start)+start;
System.out.println("这里我们将第"+n+"个元素作为基准元素");
//将我们的基准元素存储起来

int t = list[n];
list[n] = list[start];
list[start] = t;
int i,j;
//我们准备进行快排
i = start;
j = end;
//快速排序的思想就是把比基准元素小的都放在左边
//把比基准元素大的都放在右边 然后把基准元素归位
while (i != j){
//先让右哨兵动 找到合适数据后才停止
while (list[j]>=t && j>i){
j--;
}
//说明右哨兵已经选择好了 使左哨兵开始动
while (list[i]<=t && i<j){
i++;
}
//两个哨兵都找到了 交换数据
if (i<j) {
int temp = list[i];
list[i] = list[j];
list[j] = temp;
}

}
//将我们的基准元素放到合适的地方
list[start] = list[i];
list[i] = t;
//我们找到的i就是我们这一次找到的目的元素所在的位置(即第几小)
return i;
}
//交换数据函数
public void Swap(int i,int j){
int temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}

检验得程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import com.dwx.file.MyFileReader;

import java.io.File;
import java.util.List;

public class sortTest {
public static void main(String[] args) throws Exception {
//这里我们对我们存储的数据进行最简单的排序
int[] a = new int[100000];
int i;
//读取我们的数据
String fileName = "shiwan.txt";
File file = new File(fileName);
MyFileReader reader = new MyFileReader();
List<Object> objects = reader.MyFilerReader(file);
//第一个数据表示个数 可以不读
for (i=0;i<a.length;i++){
a[i] = Integer.parseInt((String) objects.get(i+1));
}
//对数组进行排序
simpleSort(a,0,a.length-1);
//输出前十个
for (i=0;i<10;i++){
System.out.println((i+1)+"================》"+a[i]);
}


}
public static void simpleSort(int[] e,int start,int end){
int i;
int j;
int temp;
int k;
i = start;
for (i=start;i<=end;i++){
temp = e[i];
k = i;
for (j=i;j<=end;j++){
//寻找每次循环的最小值
if (e[j]<temp){
temp = e[j];
k = j;
}

}
//进行交换 把最小值放到合适的位置
e[k] = e[i];
e[i] = temp;
}
}
}

经过检验,我们可以发现我们的程序是正确的

而且要比使用简单排序的全排列块的多。

动态规划——设备更新问题

动态规划——设备更新问题

这里的设备更新问题是一个书上的问题,具体的问题可以参照课本p93,作为动态规划的一个例子,我们现在解释一下动态规划的阶梯思路

可化为最短路径问题的多阶段决策问题

最优化这个问题往往可以按照动态规划来处理,其特点是,可以将一个大问题划分成若干个阶段,逐个处理每一个小问题就得到了大问题。

解题思路:

  • 可以通过构造适当的图,将它转化成最短路径问题。从而使问题变得清晰、直观;
  • 一旦转化成功,剩下的就是利用迪杰斯特拉算法将最短路径求出来 就是最优的路径

算法的实现

因为利用的是迪杰斯特拉算法,不熟悉的可以参考我这篇博文(java语言) 迪杰斯特拉算法 | dwx-tx的小天地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package com.dwx.passage2;

import java.util.Scanner;

public class shebeigengxinwenti {
//这是数学建模中地设备更新问题
public static void main(String[] args) {
//我计划 先将这些点和边存储进一个邻接矩阵里 在利用迪杰斯特拉算法就得解

//一共有11个点 需要存储在一个20x20的整数二维数组中
int[][] a = new int[20][20];
//先对这个数组进行初始化
//即 行坐标和列坐标相等就标为0
//否则标为inf(9999)
int inf = 9999;
int i,j;
for (i=0;i<20;i++){
for (j=0;j<20;j++){
if (i==j){
a[i][j] = 0;
}else {
a[i][j] = inf;
}
}
}
System.out.println("=========================================================================================");
//打印一下我们的初始化后的数组
for (int[] ints : a) {
for (int anInt : ints) {
if (anInt==inf){
System.out.print("inf"+"\t");
}else {
System.out.print(anInt+"\t");
}
}
System.out.println();
}
System.out.println("=========================================================================================");
//导入边关系
//下边我会去数有几条边 然后并记录边的权值
Scanner scanner = new Scanner(System.in);
int m;
int x,y,l;
/*
* 参数x:边的起始点
* 参数y:边的终止点
* 参数l:边的长度
* 参数m:边的总个数
* */
System.out.print("请输入边数:");
m = scanner.nextInt();
for ( j = 1;j<=m;j++){
System.out.print("请输入起始点:");
x = scanner.nextInt();
System.out.print("请输入终止点:");
y = scanner.nextInt();
System.out.print("请输入边长度:");
l = scanner.nextInt();

a[x][y] = l;
}
System.out.println("================录入数据====================");
for (int[] ints : a) {
for (int anInt : ints) {
if (anInt==inf){
System.out.print("inf"+"\t");
}else {
System.out.print(anInt+"\t");
}
}
System.out.println();
}

//启动迪杰斯特拉算法 求0点到其他点的最短距离
//一个dis数组用来存储第一行数据
int[] dis = new int [20];
for (i=0;i<20;i++){
dis[i] = a[0][i];
}

//一个book[]数组 用来存储我们加入最短路径后的数
int[] book = new int[20];
//初始化我们的book数组
for (i=0;i<20;i++){
book[i] = 0;
}
//将第一个源点读入数组
book[0] = 1;
int min;
int u = 0;
int v = 0;
//迪杰斯特拉算法的核心
for (i=0;i<20;i++){
min = inf;
//寻找距离源点最近的点
for (j=0;j<20;j++){
if (book[j]==0 && dis[j] < inf){
//则把这个数读入book
min = dis[j];
u = j;
}
}
//将这个点读入book数组
book[u] = 1;
for (v=0;v<20;v++){
//收缩调整最短路径
if (a[u][v] < inf){
if (dis[v]>dis[u]+a[u][v]){
dis[v] = dis[u]+a[u][v];
}
}
}
}
System.out.println("=================="+"处理后的最短路径"+"====================");
for (int di : dis) {
System.out.print(di+"\t");
}
System.out.println();





}
}

数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
25
0 1 16
1 2 16
2 3 16
3 4 16
0 5 16
1 6 16
2 7 16
3 8 16
4 9 16
5 10 6
6 11 6
7 12 6
8 13 6
10 14 8
11 15 8
12 16 8
14 17 11
15 18 11
17 19 18
5 2 6
6 3 6
7 4 6
10 3 8
11 4 8
14 4 11

弗洛伊德算法

弗洛伊德算法

算法思路

弗洛伊德算法比起迪杰斯特拉算法不一样,它比迪杰斯特拉多了一个循环。

迪杰斯特拉算法是求一个固定起点到其他点的最短路径 弗洛伊德算法是求图中任何点的两点间的最短路径。

算法的核心:

1
2
3
4
5
6
7
8
9
10
11
for (k=0;k<n;k++){
for (i=0;i<n;i++){
for (j=0;j<n;j++){
//弗洛伊德算法是为了改写长度
if (e[i][j]>e[i][k]+e[k][j]){
//改变长度
e[i][j] = e[i][k]+e[k][j];
}
}
}
}

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.dwx.passage2;

public class Floyd {
//这里我们写一个弗洛伊德算法
//弗洛伊德算法属于是比较好理解好学的算法了
//这里我们用e数组来存放一个二维图
private int e[][];
int inf = 99999999;

public int[][] getE() {
return e;
}

public void setE(int[][] e) {
this.e = e;
}

//编写弗洛伊德算法
public void floyd(){

//n指的是点的个数
int n = e.length;
//弗洛伊德算法的核心
//弗洛伊德算法的核心是三重循环
int i,j,k;
for (k=0;k<n;k++){
for (i=0;i<n;i++){
for (j=0;j<n;j++){
//弗洛伊德算法是为了改写长度
if (e[i][j]>e[i][k]+e[k][j]){
//改变长度
e[i][j] = e[i][k]+e[k][j];
}
}
}
}


}


}

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import com.dwx.passage2.Floyd;

import java.util.Scanner;

public class floydTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入有几个点:");
int n = scanner.nextInt();
int[][] a = new int[n][n];
//我们已经是彻底改变为0的初始化了
//下边我们读入边的关系 我们写一个有向图的吧
System.out.print("请输入边数:");
int m =scanner.nextInt();
int inf = 99999999;
//先对其进行初始化 要求i=j为0 其余为无穷
int z ,h;
for (z=0;z<n;z++){
for (h=0;h<n;h++){
if (z==h){
a[z][h] = 0;
}else {
a[z][h] = inf;
}
}
}


for (int i = 1;i <= m;i++){
System.out.print("输入点a:");
int x = scanner.nextInt();
System.out.print("输入b:");
int y = scanner.nextInt();
System.out.print("输入边长");
int l = scanner.nextInt();
a[x-1][y-1] = l;
}
for (int[] ints : a) {
for (int anInt : ints) {
if (anInt!=inf)
System.out.print(anInt+"\t");
else
System.out.print("inf"+"\t");
}
System.out.println();
}
System.out.println("===============================");

//调用弗洛伊德算法进行处理
Floyd floyd = new Floyd();
floyd.setE(a);
floyd.floyd();
int[][] e = floyd.getE();
for (int[] ints : e) {
for (int anInt : ints) {
if (anInt!=inf)
System.out.print(anInt+"\t");
else
System.out.print("inf"+"\t");
}
System.out.println();
}

}
}

MATLAB统计工具箱中的回归分析命令

MATLAB统计工具箱中的回归分析命令

多元线性回归

多元线性回归的命令是regress,此命令也可以用于一元线性回归,其格式如下:

  • 确定回归系数的点估计值,用命令b = regress(Y,X)

  • 求回归系数的点估计和区域估计,并检验回归模型,用命令

    [b, bint, r, rint, stats] = regress(Y,X,alpha)

  • 画出残差及其置信区间,用命令rcoplot(r,rint)

多项式回归

一元多项式回归

一元多项式回归可用命令:polyfit,ployval,ployconf来实现

步奏:

  1. 回归

    • 确定多项式系数的命令:[p ,S] = polyfit(x,y,m)

      其中x = (x1,x2,x3,..,xn),y = (y1,y2,y3,…,yn),p = (a1,a2,…,am+1)是多项式对的系数,S是一个矩阵,用于估计预测误差

    • 一元多项式回归命令:ploytool(x,y,m)

      此命令产生一个交互画面

  2. 预测和预测误差估计

    • Y = polyval(p,x),求polyfit所得的回归多项式在x处的预测值Y;
    • [Y,DELTA] = polyconf(p,x,S,alpha),求ployfit所得的回归多项式在x处的预测值Y及预测值得置信水平为1-alpha的置信区间[Y-DELTA,Y+DELTA];alpha的缺省值为0.05

多元二项式回归

多远二项式回归用命令rstool(x,y,’model’,alpha)其中输入数据x,y分别为nxm矩阵和n维列向量;alpha为显著性水平(缺省值为0.05);model在下列4的模式中选一个

  • linear(线性)
  • purequadratic(纯二次)
  • interaction(交叉)
  • quadratic(完全二次)

非线性回归

非线性回归可用命令 nlinfit,nlintool,nlpredci来实现

  1. 回归

    1. 确定回归系数的命令:

      [beta,r,J] = nlinfit(x,y,’model’,beta0)

      其中,数据x,y分别是nxm矩阵和n维列向量,对一元非线性回归,x为n维列向量,model是事先用M文件定义的非线性函数;beta0是回归系数的初值,beta是估计出的回归系数,r(残差)和J(Jacobian)矩阵是估计预测误差需要的数据

    2. 非线性回归命令:

      alpha为显著性水平,缺省值为0.05

  2. 预测和预测误差估计

    [Y, DELTA] = nlpredci(‘model’,x,beta,r,J)

逐步回归

逐步回归的命令是stepwise,它提供一个交互画面

命令为:stepwise(x,y)

x是nxm矩阵,y是nx1矩阵

MATLAB作图

MATLAB作图

二维图形

曲线图

  • plot(X,Y,S)
  • plot(X,Y)
  • plot(X,Y1,S1,X,Y2,S2,…,X,Yn,Sn)

元素分析

  • X,Y是向量,分别表示点集的横坐标和纵坐标
  • 命令plot(X,Y,S)描绘该点集所表示的曲线
  • S是表示线的类型

S元素的取值:

取值 意义
y 黄色
m 洋红
c 蓝绿色
r 红色
.
o
x
+ 十字
- 实线
取值 意义
短虚线
-. 长短线
长虚线

符号函数(显函数、隐函数、参数函数)画图

符号函数画图可以通过命令”ezplot”或”fplot”来实现

ezplot的调用格式

表示方式 意义
ezplot(f) 表示默认区间[-2π,2π]上绘制f = f(x)的函数
ezplot(f,[ a, b]) 表示在[a,b]上绘制显函数f = f(x)的图形
ezplot(f,[xmin,xmax,ymin,ymax]) 表示在区间[xmin,xmax]和[ymin,ymax]上绘制隐函数f(x,y)=0的图像
ezplot(fun,lims) 表示在区间[tmin,tmax]上绘制参数方程x = x(t),y = y(t)的图形

fplot(fun,lims)表示描绘字符串fun指定的函数在lims = [xmin,xmax]的图形

要求

  • fun必须是M文件的函数名或是独立变量为X的字符串,此字符串被送入函数eval
  • 函数fun(x)必须对向量中的每个元素x返回一行向量

极坐标图

命令ploar(theta, rho, s)表示用角度theta(弧度表示)和级半径rho作极坐标图,用S指定线型

三维图形

三维曲线

  • 一条曲线 plot3(x,y,z,S)
  • 多条曲线plot3(X,Y,Z,S),这里的X,Y,Z都是mxn矩阵对应的每一列表示一条曲线

空间曲线:

  • surf(X,Y,Z)
  • mesh(X,Y,Z)

处理图形

在图形上加格栅、图例、标注

  • grid on, grid off grid on表示在当前图上加上格栅,命令grid off表示删除格栅
  • hh = xlabel(‘string’) 在当前图形的x轴上加上图例string
  • hh = ylable(‘string’) 在当前图形的y轴上加上图例string
  • hh = zlable(‘string’) 在当前图形的z轴上加上图例string
  • hh = title(‘string’) 在当前图形的顶端加上图例string

定制坐标

  • axis([XMIN XMAX YMIN YMAX ZMIN ZMAX])
  • axis auto

命令axis([XMIN XMAX YMIN YMAX ZMIN ZMAX])定制图像坐标XMIN XMAX YMIN YMAX ZMIN ZMAX分别为x,y,z的最小值和最大值

命令axis auto将坐标轴返回到自动缺省值

图像保持

  • hold on,hold off
  • H = figure
  • figure(H)

命令 H= =figure创建图像并返回图形的句柄

命令figure(H)新建H窗口,激活图形H使其可见,并把它至于其他图形上方

图区控制

  • H = subplot(mrows, ncols, thisPlot)
  • subplot(mrows, nclos, thisPlot)
  • subplot(1,1,1)

命令H = subplot(mrows, ncols, thisPlot)划分整个作图区域为mrows * ncols,并激活第thisPlot块

命令subplot(mrows, nclos, thisPlot)激活已划分为mrows * ncols块的屏幕中的第thisPlot块

命令subplot(1,1,1)返回分割状态

缩放图形

  • zoom on
  • zoom off

散点图

  • 二维散点图: scatter(X,Y,S,C)

    scatter(X,Y,S,C)在向量X和Y的指定位置显示彩色圈,X和Y必须大小相同

  • 三维散点图: scatter3(X,Y,Z,S,C)

    scatter3(X,Y,Z,S,C)在向量X,Y和Z指定的位置上显示彩色圆圈,向量X,Y的Z的大小必须相同

等值线图

  • 平面等值线图: contour(x,y,z,n)

    表示绘制n个等值线的二维等值线图

  • 空间等值线图:contour3(x,y,z,n)

matlab入门

matlab入门

变量与函数

变量

matlab中变量的命名规则是:

  • 变量名必须是不含空格的单个词;
  • 变量名区分大小写;
  • 变量名最多不超过19个字符;
  • 变量名必须是字母打头,后边可以是任意字母、数字或下划线,变量名中不允许出现标点符号

MATLAB还有几个特殊变量

特殊变量 取值
ans 用于结果的缺省变量名
pi 圆周率
eps 计算机的最小数,和1相加就产生了一个比1大的数
flops 浮点运算数
inf 无穷大
NaN 不定量
i,j i = j =根号下-1
realmin 最小可用的正实数
realmax 最大可用的负实数

数学运算符号及标点符号

数学运算符号表

符号 意义
+ 加法运算,适用于两个数或两个同阶矩阵相加
- 减法运算
* 乘法运算
.* 点乘运算
./ 点除运算
^ 乘幂运算
\ 反斜线表示左除

MATLAB中标点符号的含义:

  • MATLAB的每条命令后,若为逗号或无标点符号,则显示命令的结果;若为分号,这禁止显示结果。
  • “%”后面所有的文字为注释
  • “…”表示续行

数学函数

常用基本函数

函数 名称
sin 正弦函数
cos 余弦函数
tan 正切函数
abs 绝对值(模)
min 最小值
sqrt 开平方
log 自然对数
sign 符号函数
asin 反正弦函数
函数 名称
acos 反余弦函数
atan 反正弦函数
max 最大值
sum 元素的总和
exp 以e为底的指数
log10 以10为底的对数
fix 取整

函数M文件

MATLAB定义新函数,必须编写函数M文件

函数M文件是文件后缀为m的文件,这类文件的第一行必须是以一特殊字符function开始,格式为:

function 因变量名 = 函数名(自变量名)

函数M文件的文件名必须与函数名完全一致

数组与矩阵

数组

数组的建立:

方法 意义
x = [ a b c d e f ] 创建包含指定元素的行向量
x = first : last 创建从first开始,加1计数,到last结束的行向量
x =first : increment : last 创建从first开始,加increment计数,到last结束的行向量
linspace( first , last , n ) 创建从first开始,到last结束。有n个元素的行向量

数组元素的访问:

为了访问数组元素(分量),可对数组元素进行编扯

(1)访问一个元素:数组元素可以用下标访问,如x(i)表示数组x的第i个元素

(2)访问一块元素:访问矩阵的某些元素或子块.x(a : b : c)表示访问数组x的从第a个元素开始,以步长为b到第c个元素(但不超过c),b可以为负数,b缺省时为1

(3)直接使用元素编址序号.x([ a b c d ])表示提取数组x的第a,b,c,d个元素构成一个新的数组[x(a) x(b) x(c) x(d)].

数组的方向:

数组的运算:

(1)标量-数组运算

数组对标量的加、减、乘、除、乘方是数组的每个元素对该标量施加相应的加、减、乘、除、乘方运算

(2)数组-数组运算

当两个数组有相同维数时,加、减、乘、除、幂运算可按元素对元素方式进行,不同大小或维数的数组是不能进行运算的

矩阵

矩阵的建立

逗号或空格用于分隔某一行的元素,分号用于区分不同的行

MATLAB提供了几个建立特殊矩阵的命令:

命令 意义
a = [] 产生一个空矩阵,当对一项操作无结果是=时,返回空矩阵,空矩阵的大小为0
b = zeros(m,n) 产生一个m行n列的零矩阵
c = ones(m,n) 产生一个m行n列的元素全为1的矩阵
d = eye(m,n) 产生一个m行n列的单位矩阵

矩阵中元素的操作:

  • 矩阵A的第r行:A(r,:);
  • 矩阵A的第r列:A(:,r);
  • 依次提取矩阵A的每一列,将A拉伸为一个列向量:A(:);
  • 取矩阵A的第i1i2行、第j1j2列,构成新矩阵:A(i1:i2,j1:j2);
  • 以逆序列提取矩阵A的第i1~i2列,构成新矩阵:A(i2 : -1 :i1,:);
  • 以逆序列提取矩阵A的第j1~j2列,构成新矩阵: A(:,j2: -1 :j1);
  • 删除A的第i1~i2行,构成新的矩阵:A(i1:i2,:)=[];
  • 删除A的第j1~j2列,构成新的矩阵:A(:,j1:j2)=[];
  • 将矩阵A和B拼接成新矩阵:[ A B ]或[ A ; B ].

矩阵中的运算:

  • 标量-矩阵运算:与标量-数组运算类似.
  • 矩阵-矩阵运算:矩阵的元素对元素的运算,与数组的数组-数组运算类似

线性代数中定义矩阵运算的命令如下:

  • 矩阵加法:A + B;

  • 矩阵乘法: A * B;

  • 方阵的行列式:det(A);

  • 方阵的逆:inv(A);

  • 方阵的特征值与特征向量:[ V, D] = eig( A )

线性规划

线性规划

​ 线性规划一般的形式是:

minx z = f(x) (1)

s. t. gi(x)<=0 (i=1,2,…,m) (2)

(1)和(2)一起构成的是约束优化

只有式(1)就是无约束优化

f(x)是目标函数

gi(x)<=0是约束条件

线性规划模型

建立线性规划模型有三个基本步奏:

第一步,找出待定的位置变量,并用符号表示他们

第二步,找出问题中所有的限制或约束,写出未知变量的线性方程或线性不等式

第三步,找到模型的目标或判据,写成决策变量的线性函数,以便求其最大值或最小值

线性规划实例及编程求解

实际建模中,常用的解法:

  • 图解法
  • LINGO软件包求解
  • Excel中的规划求解
  • MATLAB软件包求解

用MATLAB优化工具箱解线性规划

MATLAB软件求解线下规划的命令如下:

  • x = linprog(c,A,b)

    用于求解模型

                     min z = cx
    

    ​ s.t. Ax <= b

  • x = linprog(c,A,b,Aeq,beq)

    用于求解模式

    ​ min z = cx

    ​ s.t.Ax <= b

    ​ Aeq.x=beq

    若没有约束条件Ax<=b,则另A =[],b =[]

  • x = linprog(c,A,b,Aeq,beq,vlb,vub)

    用于求解模型

    ​ min z = cx

    ​ s.t. Ax <= b

    ​ Aeq.x = beq

    ​ vlb<=x<=vub

    没有等式约束Aeq.x=beq,则令Aeq=[],beq=[]

  • x = linprog(c,A,b,Aeq,beq,vlb,vub,x0)

    也用于求解模型3,其中x0表示初始点

  • [x,fval] = linprog(…)

    返回最优解x及x处的目标

  • Copyrights © 2015-2023 dwx
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信