路径之谜
小明冒充X星球的骑士,进入了一个奇怪的城堡。
城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n x n 个方格。【如图1.png】所示。
按习俗,骑士要从西北角走到东南角。
可以横向或纵向移动,但不能斜着走,也不能跳跃。
每走到一个新方格,就要向正北方和正西方各射一箭。
(城堡的西墙和北墙内各有 n 个靶子)
同一个方格只允许经过一次。但不必做完所有的方格。
如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
有时是可以的,比如图1.png中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)
输入:
第一行一个整数N(0<N<20),表示地面有 N x N 个方格
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出:
一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3....
比如,图1.png中的方块编号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
示例:
用户输入:
4
2 4 3 4
4 3 3 3
程序应该输出:
0 4 5 1 2 3 7 11 10 9 13 14 15
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
暴力的dfs在数据量大的时候会超时的,
我在做这道题的时候,每次dfs前判断下一个位置的箭是否已经射的多了?如果已经射的多了,肯定不可以再往前走
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
//地图
static int[][] plat;
//墙上的箭,一共有多少?
static int[][] arc;
static int n;
public static void main(String args[]){
Scanner input = new Scanner(System.in);
n = input.nextInt();
plat = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
plat[i][j] = i*n+j;
}
}
arc = new int[2][n];
for(int i=0;i<2;i++){
for(int j=0;j<n;j++){
arc[i][j] = input.nextInt();
}
}
//动态的我已经射的键的数量
//she
int[][] she = new int[2][n];
Set<Integer> set = new LinkedHashSet<Integer>();
dfs(0,0,set,she);
}
//x ,y 骑士现在的位置
//she[][] 我射的键的数量
//set保存骑士的路过位置
static void dfs(int x,int y,Set<Integer> set,int[][] she){
//每走到一个位置塞入集合代表我走过了
set.add(plat[x][y]);
//射箭
++she[0][y];
++she[1][x];
if(x==n-1&&y==n-1){
if(check(she)){
System.out.println(print(set));
}
}else{
//这里用到dfs剪枝
//如果射的箭会超过限定直接不让射箭
if(x-1>=0
&&!set.contains(plat[x-1][y])
&&she[0][y]<arc[0][y]
&&she[1][x-1]<arc[1][x-1]){
dfs(x-1,y,set,she);
}
if(x+1<n
&&!set.contains(plat[x+1][y])
&&she[0][y]<arc[0][y]
&&she[1][x+1]<arc[1][x+1]){
dfs(x+1,y,set,she);
}
if(y-1>=0
&&!set.contains(plat[x][y-1])
&&she[0][y-1]<arc[0][y-1]
&&she[1][x]<arc[1][x]){
dfs(x,y-1,set,she);
}
if(y+1<n
&&!set.contains(plat[x][y+1])
&&she[0][y+1]<arc[0][y+1]
&&she[1][x]<arc[1][x]){
dfs(x,y+1,set,she);
}
}
//回溯
set.remove(plat[x][y]);
//拔箭
--she[0][y];
--she[1][x];
}
//判断射箭数是否对应
static boolean check(int[][] she){
for(int i=0;i<2;i++){
for(int j=0;j<n;j++){
if(arc[i][j]!=she[i][j])return false;
}
}
return true;
}
//打印set
static String print(Set<Integer> set){
StringBuilder buf = new StringBuilder();
for (Integer integer : set) {
buf.append(integer+" ");
}
return buf.toString().trim();
}
}