您的位置:首页 > 编程语言 > Java开发

动态规划 和 图遍历的结合应用

2016-04-11 06:23 288 查看
遍历图通常用到的方式为dfs, bfs, 或者拓扑排序。 但是对于某些特定的情况,用动态规划去遍历图是非常有效率的,避免了重复计算已经计算过的vertex。

一个很好的例子: 有n个长宽[a, b] 不同的矩形, 如果一个矩形的长宽小于另一个矩形的长宽或者宽长,则这个矩形可以被大的那个嵌套, 则最多嵌套多少个矩形在一起。

这个题目可以用动态规划和深搜去做,dfs的效率要低得多。 思路就是读入一个包含a ,b的二维数组,遍历整个数组,如果有一个矩形可以嵌套另一个,则在另一个二维数组里的相应位置记上1, 即 if(a > A && b > B || a > b && b > A) arc[i[a]][j[a]] = 1; 如此建立一个只包含 01 的数组, 可以看出 这个数组这个有向图。 则问题转化为图的最长路径问题。

图的最长路径解: dfs: 以每一个row 为点 找出可以嵌套的矩形, 找到就向下继续找那个矩形可以嵌套哪些其他的矩形, 直至无法嵌套,更新路径长度在每一个vertical 上, 最后找到数组里最大值, 输出即可

比如说: 1 到 【2,3,5】, 5 到 【2, 3  ,6】 , 1是起点, 更新为1个矩形, 当深搜到 2 3 5三条路时 每一条路都更新递增一个1, 就是 【2,3,5】 都为2, 然后起点为5, 下层为 【2, 3, 6】 则 【2, 3 , 6】 都为 3, 这样第二层的 2 3 也同步为3. 在每次更新数量的时候, 需要比较 当前的数量 和 要更新为的数量的大小, 去大值。

DP: 递推式   dp[curr] = max{dp[n0], dp[n1], dp[n2]...}  转移为 dp[curr] = max{dp[curr], dp[next] + 1}

package DynaProg;

import java.util.Arrays;
import java.util.Random;
import java.util.Stack;

public class dp7
{
static final int numOfRec = 10;
static int[][] rec = new int[numOfRec][];
static int[][] arc = new int[numOfRec][numOfRec];
static int[][] test = {{23, 4}, {1, 1}, {4, 31}, {40, 35}};

public static void main(String[] args)
{
Random r = new Random();
for(int i = 0; i < numOfRec; i++)
{
rec[i] = new int[]{r.nextInt(numOfRec * 10) + 1, r.nextInt(numOfRec * 10) + 1};
}
//print rec list
for(int i = 0; i < numOfRec; i++)
{
for(int j = 0; j < 2; j++)
{
System.out.print(rec[i][j] + " ");
}
System.out.print("|");
}
System.out.println("\n-------------------");
find();
}

public static void find()
{
int[] dp = new int[numOfRec];
for(int i = 0; i < numOfRec; i++)
{
for(int j = 0; j < numOfRec; j++)
{
if(i != j && rec[i][0] > rec[j][0] && rec[i][1] > rec[j][1]
|| rec[i][1] > rec[j][0] && rec[i][0] > rec[j][1])
{
arc[i][j] = 1;
}
}
}
//print arc
for(int i = 0; i < numOfRec; i++)
{
for(int j = 0; j < numOfRec; j++)
{
System.out.print(arc[i][j] + " ");
}
System.out.println();
}
Stack<Integer> stack = new Stack<Integer>();
int temp = 0;
boolean flag = false;
for(int i = 0; i < numOfRec; i++)
{
stack.push(i);
while(!stack.isEmpty())
{
flag = false;
temp = stack.pop();
for(int j = 0; j < numOfRec; j++)
{
if(arc[temp][j] == 1)
{
flag = true;
stack.push(j);
dp[j] = Math.max(dp[temp] + 1, dp[j]); //dp[curr] = max{dp[parent] + 1, dp[curr]}
}
}
}
}
Arrays.sort(dp);
System.out.println(++dp[dp.length - 1]);
for(int i = 0; i < numOfRec; i++)
dfs(i);
Arrays.sort(dp2);
System.out.println(dp2[dp2.length - 1]);
}
static int[] dp2 = new int[numOfRec];

public static int dfs(int i)
{
if(dp2[i] > 0) return dp2[i];
dp2[i] = 1;
for(int j = 0; j < numOfRec; j++)
{
if(arc[i][j] == 1)
{
dp2[i] = Math.max(dp2[i], dfs(j) + 1);
//dp[curr] = max{dp[n0], dp[n1], dp[n2]...}
//dp[curr] = max{dp[curr], dp[next] + 1}
}
}
return dp2[i];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息