题目:
洛谷 P8612[蓝桥杯 2014 省 AB] 地宫取宝
题目描述
X 国王有一个地宫宝库。是 n × m n \times m n×m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是 k k k 件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k k k 件宝贝。
输入格式
输入一行 3 3 3 个整数,用空格分开: n n n, m m m, k ( 1 ≤ n , m ≤ 50 , 1 ≤ k ≤ 12 ) k(1 \le n,m \le 50,1 \le k \le 12) k(1≤n,m≤50,1≤k≤12)。
接下来有 n n n 行数据,每行有 m m m 个整数 C i ( 0 ≤ C i ≤ 12 ) C_i(0 \le C_i \le 12) Ci(0≤Ci≤12) 代表这个格子上的宝物的价值。
输出格式
要求输出一个整数,表示正好取 k k k 个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 ( 1 0 9 + 7 ) 1000000007(10^9+7) 1000000007(109+7) 取模的结果。
样例 #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 年第五届省赛
本人第一篇题解,望大佬指点!这道题主要考查了记忆化搜索,由于有四个数据我将数组设为了四维数组方便使用。本来我打算暴力搜索的,但发现超时了,无法获得满分。于是便想出了记忆化搜索。
程序
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;//将long long 定义为ll。
const int mod=1e9+7;//懂得都懂
ll record[50][50][13][13];
int map[59][59];
int n,m,k;
ll find(int x,int y,int maxv,int num)
{
if(record[x][y][maxv][num]!=-1)
return record[x][y][maxv][num];
if(x==n&&y==m)//递归终止条件:走到出口
{
if(num==k||(num==k-1&&map[x][y]>maxv))
return 1;
else
return 0;
}
if(num>k)
return 0;
if(x>n||y>m)
return 0;
ll ans=0;
if(map[x][y]>maxv)//取宝的能力
{
ans+=find(x+1,y,map[x][y],num+1);
ans+=find(x,y+1,map[x][y],num+1);
}
ans+=find(x+1,y,maxv,num);
ans+=find(x,y+1,maxv,num);
record[x][y][maxv][num]=ans%mod;
return ans%mod;
}
int main()
{
ios::sync_with_stdio(false);//神奇的,可以关闭cin、cout的加速同步的东西(要配合下面使用),我这里将两个的加速同步都关了!
cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>map[i][j];
}
memset(record,-1,sizeof(record));//初始化
cout<<find(1,1,-1,0);
return 0;
}
我用它获得了 AC 。那么我这篇题解就完美收工了!