1.
#include<limits.h>
#include<iostream>
using namespace std;
void Init_Graph(int N, int k, int** S, int** C)
{
int X;
int i, j;
int temp = N;
cout << "输入边的长度:输入1 2 4 表示点1 与 2的边的长度为 4:首数字为0表示结束输入" << endl;
cin >> i;
while (i != 0)
{
cin >> j;
cin >> C[i][j];
cin >> i;
}
cout << "输入每个阶段有哪些点:输入:X 1 2 3表示该阶段有X个点,分别为1,2,3:" << endl;
for (i = 1; i <= k; i++)
{
cout << "输入第" << i << "阶段的状态的点数:";
cin >> X;
cout << "这些点分别为:";
for (j = 0; j < X; j++)
{
cin >> S[i][j];
}
}
}
void Plan(int N, int k, int** S, int** F, int** C, int* result)
{
int i, j, t = N;
int m;
int point;
//cout<<S[k][0]<<" ";
point = S[k][0];
for (i = k - 1; i >= 1; i--)//阶段
{
j = 0;//i阶段的状态
while (S[i][j] != 0)//状态
{
m = 0;//i+1阶段的状态
F[i][j] = INT_MAX;
if (C[S[i][j]][point] == INT_MAX)
{
while (S[i + 1][m] != 0)
{
if (C[S[i][j]][S[i + 1][m]] != INT_MAX)
{
if (F[i][j] > (F[i + 1][m] + C[S[i][j]][S[i + 1][m]]))
{
F[i][j] = F[i + 1][m] + C[S[i][j]][S[i + 1][m]];
result[S[i][j]] = S[i + 1][m];
t--;
}
}
m++;
}
}
else
{
while (S[i + 1][m] != 0)
{
if (F[i][j] > (F[i + 1][m] + C[S[i][j]][S[i + 1][m]]))
{
F[i][j] = F[i + 1][m] + C[S[i][j]][S[i + 1][m]];
result[S[i][j]] = S[i + 1][m];
t--;
}
m++;
}
}
j++;
}
}
cout << "符合条件的点为:" << endl;
t = 0;
result[t] = 1;
cout << result[t] << " ";
t = result[t];
while (t < N)
{
cout << result[t] << " ";
t = result[t];
}
cout << endl << "最短距离为:";
cout << F[i + 1][0] << endl;
}
int main(int argc, char* argv[])
{
int N, k;
int i, j;
int** C, ** S, ** F;//C:边的长度,S;每个阶段的状态;F:记录每个阶段的状态中的点到终点的距离
int* result;//输出点
cout << "输入点的个数:";
cin >> N;
cout << "输入阶段数:";
cin >> k;
C = new int* [N + 1];
//C=(int **)malloc(sizeof(int*)*(N+1));
for (i = 0; i < N + 1; i++)
{
//C[i]=(int *)malloc(sizeof(int)*(N+1));
C[i] = new int[N + 1];
for (j = 0; j < N + 1; j++)
{
C[i][j] = INT_MAX;
}
}
S = new int* [N + 1];
for (i = 0; i < N + 1; i++)
{
S[i] = new int[N + 1];
memset(S[i], 0, sizeof(int) * (N + 1));
}
F = new int* [N + 1];
for (i = 0; i < N + 1; i++)
{
F[i] = new int[N + 1];
for (j = 0; j < N + 1; j++)
{
F[i][j] = 0;
}
}
result = new int[N + 1];
memset(result, 0, sizeof(int) * (k + 1));
Init_Graph(N, k, S, C);
/*
多段图的动态规划方法
阶段:k
状态:Sk:即每个阶段可供选择的点的位置
决策:u
规划方程:f(k)=min(f(k+1)+边u的长度。
f(k)表示:k点到终点的最短路径长度
初始值:F(k)=0;
*/
Plan(N, k, S, F, C, result);
delete[]result;
for (i = 0; i < N + 1; i++)
{
delete[]C[i];
}
delete[]C;
for (i = 0; i < N + 1; i++)
{
delete[]S[i];
}
delete[]S;
for (i = 0; i < N + 1; i++)
{
delete[]F[i];
}
delete[]F;
return 0;
}
C代码,照着提示输入矩阵即可。
2.
这道题根据每个人的学号不同,矩阵也会不同,就不贴图片了。
3.
package TWO;
public class Array {
/**
* 求解最优值
* @param p: 矩阵维数信息数组
* @param m: 存放最优值数组, 上三角形式
* @param s: 存放分割位置下标的数组
* @return 返回最优值
**/
public static int matrixChain(int[] p, int[][] m, int[][] s) {
int n = p.length - 1;
for (int i = 1; i <= n; i++)
// 本身为0
m[i][i] = 0; // 初始化二维数组
for (int r = 2; r <= n; r++) {
for (int i = 1; i <= n - r + 1; i++) {
int j = i + r - 1;
// 先以i进行划分
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j]; // 求出Ai到Aj的连乘
s[i][j] = i; // 记录划分位置
for (int k = i + 1; k < j; k++) {
// 寻找是否有可优化的分割点
int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; // 公式
if (t < m[i][j]) {
m[i][j] = t;
s[i][j] = k;
}
}
}
}
return m[1][n];
}
public static void traceback(int i, int j, int[][] s) {
// 输出A[i:j] 的最优计算次序
if (i == j) {
// 递归出口
System.out.print("A"+i);
return;
} else {
System.out.print("(");
// 递归输出左边
traceback(i, s[i][j], s);
// 递归输出右边
traceback(s[i][j] + 1, j, s);
System.out.print(")");
}
}
public static void main(String[] args) {
int[] p = new int[]{5, 10, 3, 12, 5,50,6};
int[][] m = new int[p.length][p.length];
int[][] s = new int[p.length][p.length];
System.out.println("最优值为: "+matrixChain(p, m, s));
traceback(1, p.length-1, s);
}
}
package TWO;
public class DynamicProgramming {
public static void main(String[] args) {
int p[] = {11,21,31,33,43,53,55,65}; // 物品价格
int w[] = {1,11,21,23,33,43,45,55}; //物品重量
int packWeight = 110;
int v[][] = new int[w.length+1][packWeight+1]; // 动态规划价格表
int putIn[][] = new int[w.length+1][packWeight+1]; // 用于记录物品是否被放入,放入为1
// 第一行,第一列都为0
for (int i = 0; i < v[0].length; i++) {
v[0][i] = 0;
}
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;
}
// 从索引为1的行开始,从索引为1的列开始
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
// 如果第i-1个物品的重量大于此时背包重量j,那么这个物品就不能放入背包中
// 表就应该填入上一个满足要求的价格
if (w[i-1] > j){
v[i][j] = v[i-1][j];
}
// 如果第i-1个物品的重量小于或等于此时背包的重量j,那么就判断这个物品的价格是否
// 大于上一个满足要求的价格,如果小于就填入将上一个满足要求的价格,否则就填入该
// 物品的价格加上剩余重量满足的最大价格
if (w[i-1] <= j){
//v[i][j] = Math.max(v[i-1][j], v[i-1][j-w[i-1]]+p[i-1]);
if (v[i-1][j] < v[i-1][j-w[i-1]]+p[i-1]){
v[i][j] = v[i-1][j-w[i-1]]+p[i-1];
putIn[i][j] = 1; // 记录物品被放入
}else {
v[i][j] = v[i-1][j];
}
}
}
}
// 输出最大价格放入的物品
int i = putIn.length-1;
int j = putIn[0].length-1;
int Price = 0;
while (i>0 && j>0){
if (putIn[i][j] == 1){
System.out.println("第"+i+"个物品放入背包中");
Price += p[i-1]; // 求价格总和
j -= w[i-1];
// 每输出一个商品,就减去该商品的重量,求出书包剩下的重量,对应价格表中的索引
}
i--;
}
System.out.println("最大价格: "+Price+"元");
// for (int[] ints : v) {
// System.out.println(Arrays.toString(ints));
// }
//
// for (int[] ints : putIn) {
// System.out.println(Arrays.toString(ints));
// }
}
}