2014蓝桥杯之地宫取宝

地宫取宝
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。

输入

输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)

接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值

输出
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。

样例输入
2 3 2
1 2 3
2 1 5
样例输出
14

解法:
dfs,注意过程中完成记录当前的宝物数值,,拿不拿的状态

import java.util.Scanner;

public class Main{
	
	private static int n;
	private static int m;
	private static int k;//k件宝物
	
	private static int[][] data;
	
	
	private static int count = 0;
	
	
	private static boolean pandaun(int i,int j,int k_count,int[] baowu) {  //判断这个宝物可不可以取
		int flag = 1;
		
		for(int di=0;di<k_count;di++) {
			
			if(data[i][j]<=baowu[di]) {
				flag = 0;
				break;
			}
		}
		if(flag==1) {
			return true;
		}
		return false;
	}
	
	private static void dfs(int i,int j,boolean na,int k_count ,int[] baowu) {//na代表取不取,k_count代表当前存储的宝物下标,baowu数组代表当前存储的所有宝物
		
		if(na) {
			baowu[k_count] = data[i][j]; //把要拿的宝物放进去
			k_count++;
		}
		
		if(i==n-1&&j==m-1) {  //dfs结束条件
			if(k_count==k) {
				count = count % 1000000007;
				count++;
			}
			return ;
		}
		
		for(int di=0;di<=1;di++) {
			for(int dj=0;dj<=1;dj++) {
				
				if(di+dj==1&&(i+di<n)&&(j+dj<m)) {//保证向右或者向下,并且没有超出数组
					
					if(pandaun(i+di, j+dj,k_count,baowu)) {//如果判断出可以拿
						
						dfs(i+di, j+dj, true,k_count,baowu); //进行dfs拿了当前宝物的情况
						
					}
					dfs(i+di, j+dj, false,k_count,baowu);//进行dfs没拿当前宝物的情况
					
				}
				
			}
		}
		
	}

	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		m = scanner.nextInt();
		k = scanner.nextInt();//k件宝物
		
		data = new int[n][m];
		
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				data[i][j] = scanner.nextInt();
			}
		}
		
		
		int[] baowu = new int[n*m];
		
		dfs(0, 0,true,0,baowu);//拿了第一件宝物
		dfs(0, 0,false,0,baowu);//没拿第一件宝物
		
		System.out.println(count);
		
	}
	
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值