一道网易笔试题
2015-10-08 08:39
357 查看
题目描述如下:
现有一个m行n列的格子棋盘,每一个格子附有一个权值,权值可以为正负零。现在要求找出一条走线,将一个棋子从第一行移到第m行,使得经过所有格子的权值之和最大,说明算法思想,给出具体的实现,并分析时间和空间复杂度,这条走棋路线需要满足如下要求:
1)起始格子可以为第1行的任意一个格子
2)终止格子可以为第m行的任意一个格子
3)走棋招法要求不许后退,并满足象棋中的兵路,士路,或者马路,也即:
对于线路中一步走棋(X1,Y1),(X2,Y2)满足:
x2>x1(只需向前,不许后退)
x2=x1+1,y2=y1,兵路,直行
或者
x2=x1+1,y2=y1-1或者y2=y1+1,士路,斜行
或者
x2=x1+1,y2=y1-2或者y2=y1+2,马路,横向‘日’字
或者
x2=x1+2,y2=y1-1或者y2=y1+1,马路,纵向‘日’字
如图1所示:
图1
从权值为8的方格开始,权值之和最大的走棋路线是:8 --> 9 --> 12 --> 19。
分析解答过程如下:
1)算法初步分析:要想一次性找到一条权值最大的路径比较复杂,因为起始位置有n个,而且对于每一个 位置而言,下一步的走法有5种(两个横日,两个纵日,兵路)。因此对于这个情况比较多的寻找最长路径 的问题,我们可以根据它的特点来建立一种数据结构。很显然,我能想到的一种数据结构是有向图。
2)算法详细分析:建立有向图这种结构我觉得有两种思路
a)思路一:将第一行的n个格子当做树的根,这样就可以创建n棵树。树中节点的分支数最多为7,树的 叶节点均分布在第m行,根节点都在第1行。
b)思路二:建立一个虚根节点,另其权值为0。该根节点的分支为第一行的所有格子,共n棵子树。
建立了有向图之后(如图2所示,一棵树的一部分),我们就可以按照深度优先搜索算法或者广度优先搜索 算法来寻找一条权值最长的路径。
图 2
代码实现如下(该实现方法基于思路一):
package
org.min.algorithm;
import
java.util.ArrayList;
import
java.util.LinkedList;
import
java.util.List;
import
java.util.Random;
import
java.util.Scanner;
public
classMaxWeightRoad
{
public
static
void main(String[] args)
{
int
m = 0, n= 0;//m行n列的棋盘
Scanner in =
newScanner(System.in);
System.out.print("请输入棋盘行数m:");
m = in.nextInt();
System.out.print("请输入棋盘列数n:");
n = in.nextInt();
int[][]checkerboard
= new
int[m]
;//创建m行n列的棋盘,存放格中的权值
Random random =
newRandom();
//初始化棋盘中的格子,权值为随机生成的整数
for(int
i = 0; i< m; i++)
for(int
j = 0; j< n; j++)
{
checkerboard[i][j] = random.nextInt(30) -10;//随机生成-10~20之间的整数
}
//构建棋盘的n个有向图,用Node数据结构代表每个格子
Listroots =
newArrayList();
for(int
i = 0; i<checkerboard[0].length;i++)
{
int
row = 0,cow = i, weight = checkerboard[0][i];
Node node =
newNode(row,cow, weight);
createGraph(node, checkerboard);
roots.add(node);
}
List> roadslist =
newArrayList>();//保存n个有向图中权值之和最大的路径,共n条路径
//求每个图的权值之和最长的路径,并将该路径保存在roadslist中
for(Noderoot
: roots)
{
Listroad =
newLinkedList();
getMaxRoad(root, road);
roadslist.add(road);
}
//得到路径权值之和最大的路径
Listmn =
null;
int
weight =0;
for(List
nl: roadslist)
{
int
temp =0;
for(Node
nd: nl)
{
temp += nd.getWeight();
}
if(weight<
temp)
{
weight = temp;
m
11abf
n = nl;
}
}
//打印结果
int
maxweight= 0;
for(Node
de: mn)
{
maxweight +=de.getWeight();
System.out.print(de.toString()
+ "\t");
}
System.out.println("\n最长路径权值之和为:"
+maxweight);
}
//深度优先搜索求权值之和最长的路径
public
static
void getMaxRoad(Node node, List list)
{
int
maxweight= 0;
Listtemplist =
newLinkedList();
templist.add(node);
while()
}
//创建有向图
public
static
void createGraph(Node node,
int[][]checkerboard)
{
//得到棋盘的边界
int
height =checkerboard[0].length;
int
width =checkerboard.length;
//获取当前格子的所在的行和列
int
row =node.getRow();
int
cow =node.getCow();
int
temprow =row;
int
tempcow =cow;
Node tempnode =
null;
//兵路x=x+1
temprow = row + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//日路x=x+1,y=y-1
temprow = row + 1;
tempcow = cow - 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//日路x=x+1,y=y+1
temprow = row + 1;
tempcow = cow + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+1,y=y-2
temprow = row + 1;
tempcow = cow - 2;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+1,y=y+2
temprow = row + 1;
tempcow = cow + 2;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+2,y=y-1
temprow = row + 2;
tempcow = cow - 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+2,y=y+1
temprow = row + 2;
tempcow = cow + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
}
}
class
Node
{
private
int
row;//格子在棋盘中第几行
private
int
cow;//格子在棋盘中第几列
private
int
weight;//格子中的权值
private
List
branch;
public
Node(int
row, int
cow, int
weight)
{
this.row
=row;
this.cow
=cow;
this.weight
=weight;
this.branch
=newLinkedList();
}
public
int
getRow()
{
return
row;
}
public
int
getCow()
{
return
cow;
}
public
int
getWeight()
{
return
weight;
}
public
ListgetBranch()
{
return
branch;
}
public
StringtoString()
{
return
"("
+row
+","
+cow
+")";
}
}
现有一个m行n列的格子棋盘,每一个格子附有一个权值,权值可以为正负零。现在要求找出一条走线,将一个棋子从第一行移到第m行,使得经过所有格子的权值之和最大,说明算法思想,给出具体的实现,并分析时间和空间复杂度,这条走棋路线需要满足如下要求:
1)起始格子可以为第1行的任意一个格子
2)终止格子可以为第m行的任意一个格子
3)走棋招法要求不许后退,并满足象棋中的兵路,士路,或者马路,也即:
对于线路中一步走棋(X1,Y1),(X2,Y2)满足:
x2>x1(只需向前,不许后退)
x2=x1+1,y2=y1,兵路,直行
或者
x2=x1+1,y2=y1-1或者y2=y1+1,士路,斜行
或者
x2=x1+1,y2=y1-2或者y2=y1+2,马路,横向‘日’字
或者
x2=x1+2,y2=y1-1或者y2=y1+1,马路,纵向‘日’字
如图1所示:
图1
从权值为8的方格开始,权值之和最大的走棋路线是:8 --> 9 --> 12 --> 19。
分析解答过程如下:
1)算法初步分析:要想一次性找到一条权值最大的路径比较复杂,因为起始位置有n个,而且对于每一个 位置而言,下一步的走法有5种(两个横日,两个纵日,兵路)。因此对于这个情况比较多的寻找最长路径 的问题,我们可以根据它的特点来建立一种数据结构。很显然,我能想到的一种数据结构是有向图。
2)算法详细分析:建立有向图这种结构我觉得有两种思路
a)思路一:将第一行的n个格子当做树的根,这样就可以创建n棵树。树中节点的分支数最多为7,树的 叶节点均分布在第m行,根节点都在第1行。
b)思路二:建立一个虚根节点,另其权值为0。该根节点的分支为第一行的所有格子,共n棵子树。
建立了有向图之后(如图2所示,一棵树的一部分),我们就可以按照深度优先搜索算法或者广度优先搜索 算法来寻找一条权值最长的路径。
图 2
代码实现如下(该实现方法基于思路一):
package
org.min.algorithm;
import
java.util.ArrayList;
import
java.util.LinkedList;
import
java.util.List;
import
java.util.Random;
import
java.util.Scanner;
public
classMaxWeightRoad
{
public
static
void main(String[] args)
{
int
m = 0, n= 0;//m行n列的棋盘
Scanner in =
newScanner(System.in);
System.out.print("请输入棋盘行数m:");
m = in.nextInt();
System.out.print("请输入棋盘列数n:");
n = in.nextInt();
int[][]checkerboard
= new
int[m]
;//创建m行n列的棋盘,存放格中的权值
Random random =
newRandom();
//初始化棋盘中的格子,权值为随机生成的整数
for(int
i = 0; i< m; i++)
for(int
j = 0; j< n; j++)
{
checkerboard[i][j] = random.nextInt(30) -10;//随机生成-10~20之间的整数
}
//构建棋盘的n个有向图,用Node数据结构代表每个格子
Listroots =
newArrayList();
for(int
i = 0; i<checkerboard[0].length;i++)
{
int
row = 0,cow = i, weight = checkerboard[0][i];
Node node =
newNode(row,cow, weight);
createGraph(node, checkerboard);
roots.add(node);
}
List> roadslist =
newArrayList>();//保存n个有向图中权值之和最大的路径,共n条路径
//求每个图的权值之和最长的路径,并将该路径保存在roadslist中
for(Noderoot
: roots)
{
Listroad =
newLinkedList();
getMaxRoad(root, road);
roadslist.add(road);
}
//得到路径权值之和最大的路径
Listmn =
null;
int
weight =0;
for(List
nl: roadslist)
{
int
temp =0;
for(Node
nd: nl)
{
temp += nd.getWeight();
}
if(weight<
temp)
{
weight = temp;
m
11abf
n = nl;
}
}
//打印结果
int
maxweight= 0;
for(Node
de: mn)
{
maxweight +=de.getWeight();
System.out.print(de.toString()
+ "\t");
}
System.out.println("\n最长路径权值之和为:"
+maxweight);
}
//深度优先搜索求权值之和最长的路径
public
static
void getMaxRoad(Node node, List list)
{
int
maxweight= 0;
Listtemplist =
newLinkedList();
templist.add(node);
while()
}
//创建有向图
public
static
void createGraph(Node node,
int[][]checkerboard)
{
//得到棋盘的边界
int
height =checkerboard[0].length;
int
width =checkerboard.length;
//获取当前格子的所在的行和列
int
row =node.getRow();
int
cow =node.getCow();
int
temprow =row;
int
tempcow =cow;
Node tempnode =
null;
//兵路x=x+1
temprow = row + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//日路x=x+1,y=y-1
temprow = row + 1;
tempcow = cow - 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//日路x=x+1,y=y+1
temprow = row + 1;
tempcow = cow + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+1,y=y-2
temprow = row + 1;
tempcow = cow - 2;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+1,y=y+2
temprow = row + 1;
tempcow = cow + 2;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+2,y=y-1
temprow = row + 2;
tempcow = cow - 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
//马路x=x+2,y=y+1
temprow = row + 2;
tempcow = cow + 1;
if((temprow<
width && temprow >=0) && (tempcow <height && tempcow >= 0))
{
tempnode =
newNode(temprow, tempcow,checkerboard[temprow][tempcow]);
node.getBranch().add(tempnode);
createGraph(tempnode,checkerboard);
}
}
}
class
Node
{
private
int
row;//格子在棋盘中第几行
private
int
cow;//格子在棋盘中第几列
private
int
weight;//格子中的权值
private
List
branch;
public
Node(int
row, int
cow, int
weight)
{
this.row
=row;
this.cow
=cow;
this.weight
=weight;
this.branch
=newLinkedList();
}
public
int
getRow()
{
return
row;
}
public
int
getCow()
{
return
cow;
}
public
int
getWeight()
{
return
weight;
}
public
ListgetBranch()
{
return
branch;
}
public
StringtoString()
{
return
"("
+row
+","
+cow
+")";
}
}
相关文章推荐
- 利用drawinrect在control中画入图片和文字
- java线程笔记
- 围城
- Jquery知识小点备注
- javascript实现下拉列表和复选框的选中
- xml追加节点
- CentOS7下升级glib
- 泛型委托
- Android GridView的简单使用
- FBO
- JAVA语法基础作业
- [优化篇]Ubuntu使用corosync+pacemaker+drbd实现MySQL的HA(1)
- javascript基础资料
- CentOS源码安装gftp缺失stropts.h
- 英语阅读网站推荐
- 根据客户区大小反推窗口大小
- 5 个在 Linux 中管理文件类型和系统时间的有用命令
- 倒数阶乘之和
- 各种数据库连接方式
- switch case 语句内部变量定义