地宫取宝问题
题目详情
X 国王有一个地宫宝库,是 n×m
个格子的矩阵,每个格子放一件宝贝,每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是 k
件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k
件宝贝。
输入格式
第一行 3
个整数,n,m,k
,含义见题目描述。
接下来 n
行,每行有 m
个整数 Ci
用来描述宝库矩阵每个格子的宝贝价值。
输出格式
输出一个整数,表示正好取 k
个宝贝的行动方案数。
该数字可能很大,输出它对 1000000007
取模的结果。
数据范围
1≤n,m≤50
1≤k≤12
0≤Ci≤12
输入样例1:
2 2 2
1 2
2 1
输出样例1:
2
输入样例2:
2 3 2
1 2 3
2 1 5
输出样例2:
14
问题分析
状态分析
1
X 国王有一个地宫宝库,是 n×m个格子的矩阵 》是个二维地图至少要 二维的 f [ i ] [ j ] 来表示
2
如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿 》还需要一个维度表示它的走到【i , j 】所有物品当中的最大价值
3
当小明走到出口时,如果他手中的宝贝恰好是 k 》题目对物品的数量有要求,所以还需要走到 [ i , j ] 对手中物品的数量做出统计
4表示
f [ i ] [ j ] [ cnt ] [v ]
i 表示所在行 , j 表示所在列
cnt 表示走到 i , j 时所包含的物品的数量
v 表示所有物品中的最大值
状态转移
不选取第 【 i , i 】物品时
f[i][j][cnt][v]=(f[i][j][cnt][v]+f[i-1][j][cnt][v])%mod;
f[i][j][cnt][v]=(f[i][j][cnt][v]+f[i][j-1][cnt][v])%mod;
选取第 [ i , j ] 物品时
if(cnt>0 && v==w[i][j]){//这里需要进行判断,假设此时 [ i , j ] 物品上的价值满足最大值条件,那么可以进行
for(int s=0;s<w[i][j];s++){//对所有小于 w [ i ] [ j ] 的价值进行遍历
f[i][j][cnt][v]=(f[i-1][j][cnt-1][s]+f[i][j][cnt][v])%mod;
f[i][j][cnt][v]=(f[i][j-1][cnt-1][s]+f[i][j][cnt][v])%mod;
}
}
代码展示
#include<iostream>
using namespace std;
const int N =53,M=15,mod=1e9+7;
int f[N][N][M][M],w[N][N];
int n,m,k;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>w[i][j];
w[i][j]++;//这里我们将 物品价值 +1 是为了处理边界
// 由于物品的价值是 0 ~ 12 ,且f [1] [1] [0] [0]表示在(1,1)处不选
//选取物品数量是0,总价值是0
//但是还会存在选取物品但是价值为 0 的情况,最后面的那个0就会有2个含义,为了方便计算
//我们将所有物品价值+1 ,且这样的操作不会影响总结果
}
}
f[1][1][0][0]=1;//f [1] [1] [0] [0]表示在(1,1)处不选
//选取物品数量是0,总价值是0
f[1][1][1][w[1][1]]=1;//f [1] [1] [0] [0]表示在(1,1)处不选
//选取物品数量是1,总价值是w【i】【j】
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int cnt=0;cnt<=k;cnt++){
for(int v=0;v<M;v++){
f[i][j][cnt][v]=(f[i][j][cnt][v]+f[i-1][j][cnt][v])%mod;
f[i][j][cnt][v]=(f[i][j][cnt][v]+f[i][j-1][cnt][v])%mod;
if(cnt>0 && v==w[i][j]){
for(int s=0;s<w[i][j];s++){
f[i][j][cnt][v]=(f[i-1][j][cnt-1][s]+f[i][j][cnt][v])%mod;
f[i][j][cnt][v]=(f[i][j-1][cnt-1][s]+f[i][j][cnt][v])%mod;
}
}
}
}
}
}
int res=0;
for(int i=0;i<M;i++){
res=(res+f[n][m][k][i])%mod;
}
cout<<res<<endl;
return 0;
}