算法分析第二次作业

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));
//        }
    }
}


在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值