联通图形和最小花费路径(MCP)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mine_song/article/details/68941202

最小花费路径(MCP)

给定一个矩阵cost[][]和其中的一个位置(m,n),写一个函数,返回从到达(0,0)到(M,N)最小成本路径的花费。该矩阵的每个格子代表遍历该格子的花费。到达(M,N)的路径的总成本是该路径上(包括源和目标)所有的费用总和。你只能从开始位置 向右、下和右下走,也就是说,从一个给定的格子(I,J),只有(i+1,j)的(i,j +1)和(i +1, j +1)的可以通过。你可以假设所有的花费都是正整数。

例如,在下面的图中,到(2,2)的最小花费路径?


最小花费的路径,如下图高亮显示。 的路径为(0,0) – >(0,1) – >(1,2) – >(2,2)。路径的成本是8(1 + 2 + 2 + 3)。


1)最优子结构
的路径到达(M,N)必须通过3格子中的一个:(M-1,N-1)或(m-1,n)或(M,N-1)。 到达(M,N),所以最小的花费路径可以写成“3个格子最小的 加[M] [N]的花费”。

minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1)) + cost[m][n]

2)重叠子问题
以下是直接的递归实现的最小花费路径的问题,用的上面的递归函数

// 递归实现
	public static int minCostWithRu(int cost[][], int m, int n) {
		if (n < 0 || m < 0)
			return -1;
		else if (m == 0 && n == 0)
			return cost[m][n];
		else
			return cost[m][n] + Math.min(
					minCostWithRu(cost, m - 1, n - 1),
					Math.min(minCostWithRu(cost, m - 1, n), 
					          minCostWithRu(cost, m, n - 1))
					);
	}

应当指出的是,上述函数反复计算相同的子问题。 请参见下面的递归树。 这时候直接的递归解决方案的复杂性是指数,这是极其缓慢的。

mC 代表 minCost()
                                    mC(2, 2)
                          /            |           \
                         /             |            \             
                 mC(1, 1)           mC(1, 2)             mC(2, 1)
              /     |     \       /     |     \           /     |     \ 
             /      |      \     /      |      \         /      |       \
       mC(0,0) mC(0,1) mC(1,0) mC(0,1) mC(0,2) mC(1,1) mC(1,0) mC(1,1) mC(2,0)

因此,MCP问题是具有动态规划必须的两个性质 像其他典型的动态规划(DP)的问题,可通过打表已自下而上的方式避免相同的子问题重复计算。

/**
	 * @param cost
	 *            给定一个矩阵cost[m+1][n+1]
	 * @param m
	 *            要到达的横坐标,m+1行,n+1列矩阵
	 * @param n
	 *            要到达的纵坐标,m+1行,n+1列矩阵
	 * @return 从cost中计算(0,0)到(m,n)最小花费和
	 */
	public static int minCost(int cost[][], int m, int n) {
		int dp[][] = new int[m + 1][n + 1];
		dp[0][0] = cost[0][0];
		// 对第一列初始化,最优距离是累加
		for (int i = 1; i <= m; i++)
			dp[i][0] = cost[i][0] + dp[i - 1][0];
		for (int i = 1; i <= n; i++)
			dp[0][i] = cost[0][i] + dp[0][i - 1];
		for (int i = 1; i <= m; i++)
			for (int j = 1; j <= n; j++)
				// 求三个数的最小值
				dp[i][j] = Math.min(Math.min(
						dp[i - 1][j], dp[i][j - 1]), 
						dp[i - 1][j - 1]) + cost[i][j];

		return dp[m][n];
	}

联通图形(去哪儿2017校招真题)

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class S4 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			String str = sc.nextLine();
			String[] strs = str.split("\\s+");
			int n = strs.length;
			int num[] = new int[n];
			Queue<Integer> q = new LinkedList<Integer>();
			ArrayList<Integer> list = new ArrayList<Integer>();
			for (int i = 0; i < n; i++) {
				num[i] = Integer.parseInt(strs[i], 16);
				list.add(num[i]);
			}
			//类似图的广度优先遍历
			q.offer(num[0]);
			list.remove(Integer.valueOf(num[0]));
			while (!q.isEmpty()) {
				int temp = q.poll();
				if (list.contains(temp + 1)) {
					q.offer(temp + 1);
					list.remove(Integer.valueOf(temp + 1));
				}
				if (list.contains(temp - 1)) {
					q.offer(temp - 1);
					list.remove(Integer.valueOf(temp - 1));
				}
				if (list.contains(temp + 4)) {
					q.offer(temp + 4);
					list.remove(Integer.valueOf(temp + 4));
				}
				if (list.contains(temp - 4)) {
					q.offer(temp - 4);
					list.remove(Integer.valueOf(temp - 4));
				}
			}
			if (list.isEmpty())
				System.out.println("pong");
			else
				System.out.println("pang");
		}
	}
}

图的连通性问题

import java.util.LinkedList;
import java.util.Queue;

public class 连通性 {
	// 以下字段都需要初始化!!
	public int tmp[][];
	public int a[][];
	public int n = 0;
	public static int INF = Integer.MAX_VALUE;
	public boolean vis[]; // 访问数组

	public void input() {
		// 初始化tmp数组
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (a[i][j] < INF) // INF代表不通
					tmp[i][j] = tmp[j][i] = 1;
				else
					tmp[i][j] = tmp[j][i] = 0;
			}
			tmp[i][i] = 1;
		}
	}

	// warshall算法判断图的连通性
	public boolean Warshall() {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (tmp[j][i] == 1) {
					for (int k = 0; k < n; k++) {
						if (tmp[i][k] == 1)
							tmp[k][j] = tmp[j][k] = 1;
					}
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				if (tmp[i][j] == 0)
					return false;
		return true;
	}

	// 广度优先搜索判断连通性
	public boolean BFS() {

		Queue<Integer> q = new LinkedList<>();
		int count = 0;
		// 加入的是结点编号
		q.offer(0); // 0节点入队列
		while (!q.isEmpty()) {
			int v = q.poll();
			vis[v] = true;
			count++;
			// 与联通且没有被访问过节点入队列
			for (int i = 0; i < n; i++) {
				if (tmp[v][i] == 1) {
					if (!vis[i])
						q.offer(i);
				}
			}
		}

		if (count == n)
			return true; // count <= n ???
		else
			return false;

	}

	// 深度优先搜索判断图的连通性——需要驱动
	// tmp数组需要先初始化。
	public void DFS(int firstNode) {
		vis[firstNode] = true; // need将vis定义为全局变量

		for (int i = 0; i < n; i++) {
			if (tmp[firstNode][i] == 1 && !vis[i])
				DFS(i);
		}
	}

	// DFS驱动,一次深度优先遍历能否访问完所有结点
	public boolean driverDFS() {
		DFS(0); // 从0节点开始访问
		for (int i = 0; i < n; i++) {
			if (!vis[i])
				return false;
		}
		return true;
	}
}

树的中序遍历

import java.util.ArrayList;
import java.util.Stack;

class TreeNode {
	int val;
	TreeNode left;
	TreeNode right;

	public TreeNode(int val) {
		this.val = val;
	}
}

public class 树的遍历 {
	static ArrayList<Integer> list = new ArrayList<>();
	public static void main(String[] args) {
		树的遍历 s = new 树的遍历();
		TreeNode n1 = new TreeNode(1);
		TreeNode n2 = new TreeNode(2);
		TreeNode n3 = new TreeNode(3);
		TreeNode n4 = new TreeNode(4);
		TreeNode n5 = new TreeNode(5);
		TreeNode n6 = new TreeNode(6);
		TreeNode n7 = new TreeNode(7);
		n1.left = n2;
		n1.right = n3;
		n2.left = n4;
		n2.right = n5;
		n3.left = n6;
		n5.left = n7;
		s.inOrder(n1);
		System.out.println(list);
		list.clear();
		s.inOrderWithStack(n1);
		System.out.println(list);
		
	}
	public void inOrder(TreeNode root) {
		if (root != null) {
			inOrder(root.left);
			list.add(root.val);
			inOrder(root.right);
		}
	}
	public void inOrderWithStack(TreeNode root) {
		if (root == null)
			return;
		Stack<TreeNode> stack = new Stack<>();
		TreeNode p = root;
		while (p != null || !stack.isEmpty()) {
			if (p != null) {
				stack.push(p);
				p = p.left;
			} else {
				p = stack.pop();
				list.add(p.val);
				p = p.right;
			}
		}
	}
}

参考:http://www.tuicool.com/articles/fMR3An

展开阅读全文

没有更多推荐了,返回首页