这个题可以用dfs或bfs遍历迷宫,用dfs是递归地查看每一个位置,这里在每次走到一个前都要先查看青蛙的体力值够不够,不够的话,这条路就pass掉了,够的话继续往下遍历。递归结束的条件就是已经到达了出口,即[0][m-1]这个位置,当到达此位置时还要查看是否所消耗的体力是最少的。另一个问题是要记录最小路径,这里每到达一个位置就把它加入到一个数组中,位置不合适的话就把数组的下标-1,相当于把这个位置从最终路径中剔除掉。以下是dfs的代码:
public class maze {
static int n,m,P;
static int map[][] = new int[11][11];
static int minPath[][] = new int[2][100];
static int path[][] = new int[2][100];
static int move[][] = new int[][]{{-1,0,3},{0,1,1},{1,0,0},{0,-1,1}};
static int loseEnergy = 0;
static int minLoseEnergy = Integer.MAX_VALUE;
static int minSteps = 0;
static int steps = 0;
static int maxEnergy;
public static void dfs(int row,int col,int[][] map){
if(row == 0 && col == m - 1 && P >= loseEnergy){
if(minLoseEnergy > loseEnergy){
minLoseEnergy = loseEnergy;
for(int i = 0; i < 2; i++)
for(int j = 0; j < steps; j++)
minPath[i][j] = path[i][j];
minSteps = steps;
}
}
for(int i = 0; i < 4; i++){
int newRow = row + move[i][0];
int newCol = col + move[i][1];
if(newRow >= 0 && newRow < n && newCol >= 0 && newCol < m && map[newRow][newCol] == 1 && P >= loseEnergy){
steps++;
path[0][steps] = newRow;
path[1][steps] = newCol;
map[newRow][newCol] = 0;
loseEnergy += move[i][2];
dfs(newRow,newCol,map);
map[newRow][newCol] = 1;
steps--;
loseEnergy -= move[i][2];
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
m = cin.nextInt();
P = cin.nextInt();
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
map[i][j] = cin.nextInt();
}
cin.close();
map[0][0] = 0;
dfs(0,0,map);
if(minLoseEnergy == Integer.MAX_VALUE)
System.out.println("Can not escape!");
else{
for(int i = 0; i < minSteps; i++){
System.out.print("["+ minPath[0][i] +","+ minPath[1][i] +"],");
}
System.out.print("[0," + (m-1) + "]");
}
}
}
看到这个题一下想到的是母函数和0/1背包
关于母函数的详细介绍参照博客http://blog.csdn.net/supersnow0622/article/details/9666871
以题目中的例子为例,代码模拟计算(1+X^5)*(1+X^5)*(1+X^10)*(1+X^2)*(1+X^3)则计算结果中X^15的系数就是方案数,这题还要注意大数问题。
代码如下:
public class motherFunction {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n,sum,A[];
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
sum = cin.nextInt();
A = new int[n];
for(int i = 0; i < n ; i++){
A[i] = cin.nextInt();
}
System.out.println(getTypeCount(n,sum,A));
}
//母函数解法
public static BigInteger getTypeCount(int n,int sum,int[] A){
BigInteger c[] = new BigInteger[1005];
BigInteger c1[] = new BigInteger[1005];
BigInteger c2[] = new BigInteger[1005];
init(c);init(c1);init(c2);
c1[0] = BigInteger.ONE;
c1[A[0]] = BigInteger.ONE;
for(int i = 1; i < n; i++){
init(c2);
init(c);
int a = A[i];
c2[0] = BigInteger.ONE;
c2[a] = BigInteger.ONE;
for(int j = 0; j <= sum; j++){
if(c1[j] != BigInteger.ZERO){
c[j] = c[j].add(c1[j].multiply(c2[0]));
if(j + a <= sum)
c[j + a] = c[j + a].add(c1[j].multiply(c2[a]));
}
}
for(int k = 0; k <= sum; k++)
c1[k] = c[k];
}
return c1[sum];
}
public static void init(BigInteger c[]){
for(int i = 0;i < c.length; i++){
c[i] = BigInteger.ZERO;
}
}
}
关于0/1背包计算方案数博客http://blog.csdn.net/supersnow0622/article/details/9772839#comments
在这个题中可以把每个数字当作物品的体积,和sum看作容器的体积,与一般的0/1背包不一样的地方是数组中存放的是和为i的方案数。
代码如下:
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n,sum,A[];
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
sum = cin.nextInt();
A = new int[n];
for(int i = 0; i < n ; i++){
A[i] = cin.nextInt();
}
System.out.println(getTypeCount1(n,sum,A));
}
public static BigInteger getTypeCount1(int n,int sum,int[] A){
BigInteger c[] = new BigInteger[1005];
for(int i = 1;i < c.length; i++){
c[i] = BigInteger.ZERO;
}
c[0] = BigInteger.ONE;
for(int i = 0;i < n; i++){
int index = A[i];
for(int j = sum; j >= 0; j--){
if(j >= index && c[j-index]!=BigInteger.ZERO )
c[j] = c[j].add(c[j-index]);
}
}
return c[sum];
}
}