开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第35天,点击查看活动详情
[蓝桥杯 2014 省 AB] 地宫取宝
题目描述
X 国王有一个地宫宝库。是 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是 件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 件宝贝。
输入格式
输入一行 个整数,用空格分开:,,。
接下来有 行数据,每行有 个整数 代表这个格子上的宝物的价值。
输出格式
要求输出一个整数,表示正好取 个宝贝的行动方案数。该数字可能很大,输出它对 取模的结果。
样例 #1
样例输入 #1
2 2 2
1 2
2 1
样例输出 #1
2
样例 #2
样例输入 #2
2 3 2
1 2 3
2 1 5
样例输出 #2
14
提示
时限 1 秒, 256M。蓝桥杯 2014 年第五届省赛
分析
这题是个难题,是个dp,四维dp分四种情况,向右走,向下走,都不取,和向右向下走都取表示走到这个点,取了件物品,其中最大的物品价值是的方案数。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define pb push_back
#define int long long
using namespace std;
const int N=55;
const int mod=1000000007;
int w[N][N];
int n,m,k;
int dp[N][N][15][15];
int t;
signed 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]++;
}
}
dp[1][1][1][w[1][1]]=1;
dp[1][1][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(i==1 && j==1) continue;
for(int k1=0;k1<=k;k1++){
for(int c=0;c<=13;c++){
int &res=dp[i][j][k1][c];
res=(res+dp[i-1][j][k1][c])%mod;
res=(res+dp[i][j-1][k1][c])%mod;
int v=w[i][j];
if(k1>0 && c==w[i][j]){
for(int u=0;u<c;u++){
res=(res+dp[i-1][j][k1-1][u])%mod;
res=(res+dp[i][j-1][k1-1][u])%mod;
}
}
}
}
}
int ans=0;
for(int i=0;i<=13;i++){
ans=(ans+dp[n][m][k][i])%mod;
}
cout<<ans<<endl;
return 0;
}