深搜暴力,只过50%的样例
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
static final int N = 60;
static int[][] a = new int[N][N];
static int max = -1;
static int n;
static int m;
static int k;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
for(int i = 0;i < n;i++) {
for(int j = 0;j <m;j++) {
a[i][j] = scan.nextInt();
}
}
int ans = dfs(0,0,-1,0);//从0,0,位置开始,max起始值为-1,cnt代表拿了宝物的个数
System.out.println(ans);
scan.close();
}
private static int dfs(int i, int j, int max, int cnt) {
// TODO Auto-generated method stub
if(i == n || j == m || cnt > k) return 0;//边界防御情况
int cur = a[i][j];//当前值
long ans = 0;
if(i == n - 1 && j == m - 1) {
if(cnt == k || cnt== k - 1 && cur > max ) {
return 1;
}
return ans;
}
if(cur > max) {//当前值比最大值,捡起的情况
ans += dfs(i + 1,j,cur,cnt + 1);
ans += dfs(i,j + 1,cur,cnt + 1);
}
//当前值比最大值小或者当前值比最大值,不捡起的情况
ans+=dfs(i+1,j,max,cnt);
ans+=dfs(i,j+1,max,cnt);
return ans % (int) 1e9 + 7;
}
}
记忆型递归
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
//记忆型递归
public class Main {
static final int N = 60;
static int[][] a = new int[N][N];
static int max = -1;
static int n;
static int m;
static int k;
static long[][][][] st = new long[51][51][14][14];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
for(int i = 0;i < n;i++) {
for(int j = 0;j <m;j++) {
a[i][j] = scan.nextInt();
}
}
init();
long ans = dfs(0,0,-1,0);//从0,0,位置开始,max起始值为-1,cnt代表拿了宝物的个数
System.out.println(ans);
scan.close();
}
public static void init() {
for(int i=0;i<=50;i++) {
for(int j=0;j<=50;j++) {
for(int k=0;k<=13;k++) {
for(int l=0;l<=13;l++) {
st[i][j][k][l] = -1;
}
}
}
}
}
private static long dfs(int i, int j, int max, int cnt) {
if(st[i][j][max + 1][cnt] != -1) {//不等于-1,说明此前已经记录方案数,直接调用
return st[i][j][max + 1][cnt];
}
// TODO Auto-generated method stub
if(i == n || j == m || cnt > k) return 0;//边界防御情况
int cur = a[i][j];//当前值
long ans = 0;
if(i == n - 1 && j == m - 1) {
if(cnt == k || cnt== k - 1 && cur > max ) {
return 1;
}
return ans;
}
if(cur > max) {//当前值比最大值,捡起的情况
ans += dfs(i + 1,j,cur,cnt + 1);
ans += dfs(i,j + 1,cur,cnt + 1);
}
//当前值比最大值小或者当前值比最大值,不捡起的情况
ans+=dfs(i+1,j,max,cnt);
ans+=dfs(i,j+1,max,cnt);
st[i][j][max + 1][cnt] = ans % (int)(1e9 + 7);//存此时状态的方案数
return ans % (int)(1e9 + 7);
}
}
动态规划-背包问题
参考题解
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
//记忆型递归
public class Main {
static final int N = 60;
static int[][] a = new int[N][N];
static int max = -1;
static int n;
static int m;
static int k;
static final int MOD = (int) 1e9 + 7;
static int [][][][] dp = new int[51][51][14][14];//行,列,宝贝数目,最后一个物品价值
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
for(int i = 1;i <= n;i++) {
for(int j = 1;j <=m;j++) {
a[i][j] = scan.nextInt();
a[i][j]++;//将每一个价值加1,是因为当没有选任何物品时,其价值是最小的,要小于所有物品的最小值,最小值为0,则当没有选任何物品时,其价值是-1,为了防止下标越界
}
}
dp[1][1][1][a[1][1]] = 1;//第一个位置取
dp[1][1][0][0] = 1;//第一个位置不取,每个价值都加上1,所以dp[1][1][0][-1]变为dp[1][1][0][0];
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= m;j++) {
if(i == 1&& j == 1) continue;
for(int u = 0;u <= k;u++) {
for(int v = 0;v <= 13;v++) {
int val = dp[i][j][u][v];
val = (val + dp[i - 1][j][u][v]) % MOD;//从上往下,不选最后一个;
val = (val + dp[i][j - 1][u][v]) % MOD;//从左往右,不选最后一个;
for(int c = 0;c< v;c++) {
if(u >0 && a[i][j]== v) {
val = (val + dp[i - 1][j][u - 1][c]) % MOD;//从上往下,选最后一个;
val = (val + dp[i][j - 1][u - 1][c]) % MOD;//从左往右,选最后一个;
}
}
dp[i][j][u][v] = val;
}
}
}
}
int res = 0;
for(int i = 0;i <= 13;i++) {
res = (res + dp[n][m][k][i]) % MOD;
}
System.out.println(res);
scan.close();
}
}