前几天在CSDN上看人发帖问的,当时觉得很有意思就留下来了,现在找不到原帖,题意如下:
/*
* 伊万洛夫在比武大会上力克群雄,成为新一届“草原雄鹰”,
* 为部落赢得了莫大荣誉。首领决定要重重奖赏,
* 他对伊万洛夫说:“孩子,你是知道的,面前的这片草原,
* 南北向和东西向的道路纵横交错。
* 现在,路口放着纯金打造的俄罗斯娃娃,重量大小不等,重的都能装下轻的。
* 你可以沿着道路飞奔,拾取路口的娃娃,
* 要求是任何时刻必须是一个套娃,装好后就不能再拆开了。
* 注意不要走重复路。”
* 请你为伊万洛夫规划路线,使得他能够有最大的收获。
*/我想了一天左右,最后是用tree模型去实现的,(偷懒用了swing里面的DefaultMutableTreeNode类)代码如下,作抛砖引玉之用,希望有高手可以提点更优的算法,感激!
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.tree.DefaultMutableTreeNode;public class MaxSum {
//nums代表由娃娃重量组成的二维数组,x,y代表初始入口坐标
public static void findMaxSum(int[][] nums,int x,int y){
//初始化树
if(x<0||x>nums.length||y<0||y>nums[x].length){
return;
}
int rootnumber=nums[x][y];
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootnumber);
addChild(root, nums, x, y);
//获得所有的叶节点
ArrayList list = new ArrayList();
findAllLeafs(list,root);
//遍历叶节点找出所有路径
ArrayList ways = new ArrayList();
for(Object leaf:list){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) leaf;
StringBuffer way = new StringBuffer();
checkleaf(way,node);
ways.add(way.toString());
}
//对所有路径求和,找出最大值
HashMap map = new HashMap();
Integer maxSum = (Integer) root.getUserObject();
map.put(maxSum, new String[]{root.getUserObject().toString()});
for(int i =0;i<ways.size();i++){
int sum = 0;
String[] strs =((String) ways.get(i)).split(" ");
for(String str:strs){
sum+=Integer.parseInt(str);
}
map.put(sum, strs);
if(sum>maxSum){
maxSum=sum;
}
}
String[] maxWay = (String[]) map.get(maxSum);
//打印最优路径和最大获取量
System.out.println("路径为:");
for(int i = maxWay.length-1;i>=0;i--){
System.out.print(maxWay[i]);
if(i>0){
System.out.print("-->");
}
}
System.out.println();
System.out.println("最多可以拿到"+maxSum+"斤娃娃!");
}
//遍历某个叶节点-根节点的所有节点
public static void checkleaf(StringBuffer way,DefaultMutableTreeNode node ){
way.append(node.getUserObject());
way.append(" ");
Integer value = (Integer) node.getUserObject();
DefaultMutableTreeNode father = (DefaultMutableTreeNode) node.getParent();
if(father.isRoot()){
way.append(father.getUserObject());
way.append(" ");
Integer val = (Integer) father.getUserObject();
}else{
checkleaf(way,father);
}
}
//找出所有叶节点:
public static void findAllLeafs(ArrayList list,DefaultMutableTreeNode root){
for(int i =0;i<root.getChildCount();i++){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
if(child.isLeaf()){
list.add(child);
}else{
findAllLeafs(list,child);
}
}
}
//添加节点
public static void addChild(DefaultMutableTreeNode node,int[][] nums,int x,int y){
int nodenumber=(Integer) node.getUserObject();
if(y+1<nums[x].length&&nums[x][y+1]>nodenumber&&!isFather(node,nums[x][y+1])){
int childnumber = nums[x][y+1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y+1);
}
if(y-1>=0&&nums[x][y-1]>nodenumber&&!isFather(node,nums[x][y-1])){
int childnumber = nums[x][y-1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y-1);
}
if(x-1>=0&&nums[x-1][y]>nodenumber&&!isFather(node,nums[x-1][y])){
int childnumber = nums[x-1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x-1,y);
}
if(x+1<nums.length&&nums[x+1][y]>nodenumber&&!isFather(node,nums[x+1][y])){
int childnumber = nums[x+1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x+1,y);
}
}
//判断一个节点是不是另外一个节点的父节点
public static boolean isFather(DefaultMutableTreeNode child,int nodevalue){
DefaultMutableTreeNode father = (DefaultMutableTreeNode) child.getParent();
if(father ==null){
return false;
}
int value = (Integer) father.getUserObject();
if(value == nodevalue){
return true;
}else{
isFather(father,nodevalue);
}
return false;
}
public static void main(String[] args) {
int[][] nums = new int[][]{
{1,3,7,16,20},
{29,23,22,5,2},
{27,13,11,9,8},
{15,6,21,14,19}
};
int x =0;
int y =0;
findMaxSum(nums,x,y);
}
}输出结果如下:
路径为:
1-->3-->7-->22-->23-->29
最多可以拿到85斤娃娃!
/*
* 伊万洛夫在比武大会上力克群雄,成为新一届“草原雄鹰”,
* 为部落赢得了莫大荣誉。首领决定要重重奖赏,
* 他对伊万洛夫说:“孩子,你是知道的,面前的这片草原,
* 南北向和东西向的道路纵横交错。
* 现在,路口放着纯金打造的俄罗斯娃娃,重量大小不等,重的都能装下轻的。
* 你可以沿着道路飞奔,拾取路口的娃娃,
* 要求是任何时刻必须是一个套娃,装好后就不能再拆开了。
* 注意不要走重复路。”
* 请你为伊万洛夫规划路线,使得他能够有最大的收获。
*/我想了一天左右,最后是用tree模型去实现的,(偷懒用了swing里面的DefaultMutableTreeNode类)代码如下,作抛砖引玉之用,希望有高手可以提点更优的算法,感激!
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.tree.DefaultMutableTreeNode;public class MaxSum {
//nums代表由娃娃重量组成的二维数组,x,y代表初始入口坐标
public static void findMaxSum(int[][] nums,int x,int y){
//初始化树
if(x<0||x>nums.length||y<0||y>nums[x].length){
return;
}
int rootnumber=nums[x][y];
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootnumber);
addChild(root, nums, x, y);
//获得所有的叶节点
ArrayList list = new ArrayList();
findAllLeafs(list,root);
//遍历叶节点找出所有路径
ArrayList ways = new ArrayList();
for(Object leaf:list){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) leaf;
StringBuffer way = new StringBuffer();
checkleaf(way,node);
ways.add(way.toString());
}
//对所有路径求和,找出最大值
HashMap map = new HashMap();
Integer maxSum = (Integer) root.getUserObject();
map.put(maxSum, new String[]{root.getUserObject().toString()});
for(int i =0;i<ways.size();i++){
int sum = 0;
String[] strs =((String) ways.get(i)).split(" ");
for(String str:strs){
sum+=Integer.parseInt(str);
}
map.put(sum, strs);
if(sum>maxSum){
maxSum=sum;
}
}
String[] maxWay = (String[]) map.get(maxSum);
//打印最优路径和最大获取量
System.out.println("路径为:");
for(int i = maxWay.length-1;i>=0;i--){
System.out.print(maxWay[i]);
if(i>0){
System.out.print("-->");
}
}
System.out.println();
System.out.println("最多可以拿到"+maxSum+"斤娃娃!");
}
//遍历某个叶节点-根节点的所有节点
public static void checkleaf(StringBuffer way,DefaultMutableTreeNode node ){
way.append(node.getUserObject());
way.append(" ");
Integer value = (Integer) node.getUserObject();
DefaultMutableTreeNode father = (DefaultMutableTreeNode) node.getParent();
if(father.isRoot()){
way.append(father.getUserObject());
way.append(" ");
Integer val = (Integer) father.getUserObject();
}else{
checkleaf(way,father);
}
}
//找出所有叶节点:
public static void findAllLeafs(ArrayList list,DefaultMutableTreeNode root){
for(int i =0;i<root.getChildCount();i++){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
if(child.isLeaf()){
list.add(child);
}else{
findAllLeafs(list,child);
}
}
}
//添加节点
public static void addChild(DefaultMutableTreeNode node,int[][] nums,int x,int y){
int nodenumber=(Integer) node.getUserObject();
if(y+1<nums[x].length&&nums[x][y+1]>nodenumber&&!isFather(node,nums[x][y+1])){
int childnumber = nums[x][y+1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y+1);
}
if(y-1>=0&&nums[x][y-1]>nodenumber&&!isFather(node,nums[x][y-1])){
int childnumber = nums[x][y-1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y-1);
}
if(x-1>=0&&nums[x-1][y]>nodenumber&&!isFather(node,nums[x-1][y])){
int childnumber = nums[x-1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x-1,y);
}
if(x+1<nums.length&&nums[x+1][y]>nodenumber&&!isFather(node,nums[x+1][y])){
int childnumber = nums[x+1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x+1,y);
}
}
//判断一个节点是不是另外一个节点的父节点
public static boolean isFather(DefaultMutableTreeNode child,int nodevalue){
DefaultMutableTreeNode father = (DefaultMutableTreeNode) child.getParent();
if(father ==null){
return false;
}
int value = (Integer) father.getUserObject();
if(value == nodevalue){
return true;
}else{
isFather(father,nodevalue);
}
return false;
}
public static void main(String[] args) {
int[][] nums = new int[][]{
{1,3,7,16,20},
{29,23,22,5,2},
{27,13,11,9,8},
{15,6,21,14,19}
};
int x =0;
int y =0;
findMaxSum(nums,x,y);
}
}输出结果如下:
路径为:
1-->3-->7-->22-->23-->29
最多可以拿到85斤娃娃!
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;public class MaxSum {
//nums代表由娃娃重量组成的二维数组,x,y代表初始入口坐标
public static void findMaxSum(int[][] nums,int x,int y){
//初始化树
if(x<0||x>nums.length||y<0||y>nums[x].length){
return;
}
int rootnumber=nums[x][y];
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootnumber);
addChild(root, nums, x, y);
//获得所有的叶节点
ArrayList list = new ArrayList();
findAllLeafs(list,root);
//遍历叶节点找出所有路径
ArrayList ways = new ArrayList();
for(Object leaf:list){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) leaf;
StringBuffer waysb = new StringBuffer();
checkleaf(waysb,node);
String[] way = waysb.toString().split(" ");
List ls = Arrays.asList(way);
Collections.reverse(ls);
ways.add(ls);
}
int maxSum = 0;
HashMap eachWay = new HashMap();
HashMap maxWays=new HashMap();
for(Object obj:ways){
List way = (List) obj;
Object[] objs= maxSum(way,0);
int max = (Integer)objs[0];
List maxWay = (List) objs[1];
if(max>maxSum){
maxSum=max;
maxWays.put(max, maxWay);
eachWay.put(max, way);
}
}
System.out.print("最优路径:");
System.out.println(eachWay.get(maxSum));
System.out.print("要拿的娃娃为:");
System.out.println(maxWays.get(maxSum));
System.out.println("最多可以拿"+maxSum+"斤娃娃!"); }
//遍历某个叶节点-根节点的所有节点
public static void checkleaf(StringBuffer way,DefaultMutableTreeNode node ){
way.append(node.getUserObject());
way.append(" ");
DefaultMutableTreeNode father = (DefaultMutableTreeNode) node.getParent();
if(father.isRoot()){
way.append(father.getUserObject());
way.append(" ");
}else{
checkleaf(way,father);
}
}
//找出所有叶节点:
public static void findAllLeafs(ArrayList list,DefaultMutableTreeNode root){
for(int i =0;i<root.getChildCount();i++){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
if(child.isLeaf()){
list.add(child);
}else{
findAllLeafs(list,child);
}
}
}
//添加节点
public static void addChild(DefaultMutableTreeNode node,int[][] nums,int x,int y){
if(y+1<nums[x].length&&!isFather(node,nums[x][y+1])){
int childnumber = nums[x][y+1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y+1);
}
if(y-1>=0&&!isFather(node,nums[x][y-1])){
int childnumber = nums[x][y-1];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x,y-1);
}
if(x-1>=0&&!isFather(node,nums[x-1][y])){
int childnumber = nums[x-1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x-1,y);
}
if(x+1<nums.length&&!isFather(node,nums[x+1][y])){
int childnumber = nums[x+1][y];
DefaultMutableTreeNode child = new DefaultMutableTreeNode(childnumber);
node.add(child);
addChild(child,nums,x+1,y);
}
}
//判断一个节点是不是另外一个节点的父节点
public static boolean isFather(DefaultMutableTreeNode child,int nodevalue){
boolean flag = false;
DefaultMutableTreeNode father = (DefaultMutableTreeNode) child.getParent();
if(null !=father){
int value = (Integer) father.getUserObject();
if(value==nodevalue){
flag = true;
}else{
flag = isFather(father,nodevalue);
}
}
return flag;
}
/*
* 对于每一条可走的路径选出可以拿到的最大的和
* 题目转化为在一个list中按顺序找出最大的和
*/
public static Object[] maxSum(List list,int beginIndex){
DefaultMutableTreeNode root = new DefaultMutableTreeNode(list.get(beginIndex));
addChildren(root,list,beginIndex+1);
ArrayList leaflist = new ArrayList();
findAllLeafs(leaflist,root);
ArrayList ways = new ArrayList();
for(Object leaf:leaflist){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) leaf;
StringBuffer waysb = new StringBuffer();
checkleaf(waysb,node);
String[] way = waysb.toString().split(" ");
List ls = Arrays.asList(way);
Collections.reverse(ls);
ways.add(ls);
}
//对所有路径求和
HashMap wayMap = new HashMap();
Integer maxSum =0;
for(Object obj:ways){
Integer sum =0;
List waylist = (List) obj;
for(Object obj1:waylist){
sum+=(Integer.parseInt((String)obj1));
}
wayMap.put(sum, obj);
if(sum>maxSum){
maxSum=sum;
}
}
//找出最优路径:
Object[] objs = new Object[2];
List maxWay = (List) wayMap.get(maxSum);
objs[0]=maxSum;
objs[1]=maxWay;
return objs;
}
//在list中往根节点添加子节点(子节点值大于父节点值)
public static void addChildren(DefaultMutableTreeNode root,List list,int index){
if(index>=list.size()){
return;
}else{
for(int i = index;i<list.size();i++){
if(((Integer.parseInt((String) list.get(i))>(Integer.parseInt((String) root.getUserObject()))))){
DefaultMutableTreeNode children = new DefaultMutableTreeNode(list.get(i));
root.add(children);
addChildren(children,list,i+1);
}
}
}
}
public static void main(String[] args) {
int[][] nums = new int[][]{
{1,3,7,16,20},
{29,23,22,5,2},
{27,13,11,9,8},
{15,6,21,30,19}
};
int x =0;
int y =0;
findMaxSum(nums,x,y);
}
}
输出结果:
最优路径:[1, 3, 7, 16, 20, 2, 5, 9, 8, 19, 30, 21, 11, 22, 23, 13, 27, 29]
要拿的娃娃为:[1, 3, 7, 16, 20, 21, 22, 23, 27, 29]
最多可以拿169斤娃娃!
MAX(NodeX)=NodeX.value + max{MAX value of all next nodes}
请你为伊万洛夫规划路线,使得他能够有最大的收获。
Input: cross.txt
输入包括多组测试用例;
每个测试用例开始是一对整数<R, C>,R表示东西向道路数,C表示南北向道路总数;接下来R行,每行包括C个正整数(或0)W[r,c],分别表示第r条东西向道路与第c条南北向道路交叉处路口放置的俄罗斯娃娃的重量(或表示没有放置娃娃)。
Output:
输出能有最大收获的路径规划。