# 最小花费路径(MCP)

1）最优子结构

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)

/**
* @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.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];
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
num[i] = Integer.parseInt(strs[i], 16);
}
//类似图的广度优先遍历
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() {

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);
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();