问题 1436: 地宫取宝 (dp)

题目传送门

时间限制: 1Sec 内存限制: 128MB 提交: 423 解决: 94

题目描述
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记忆化搜索,这题要考虑的参数:宝物的大小和个数
所以我们要四个参数;另外由于宝物的大小可能为0,所以要初始为
-1,则dp里面要+1;
或者用dp;dp[i][j][k][c]为走到(i,j)的时候,手上共K个物品,最大价值小于c
具体看代码。

代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int n,m,kk;
ll dp[55][55][13][13];
int a[55][55];

ll dfs(int x,int y,int num,int c)
{
    if(dp[x][y][num][c+1]!=-1) return dp[x][y][num][c+1];
    if(x==n&&y==m) {
        if(num==kk) return 1;
        if(num==kk-1&&a[x][y]>c) return 1;
    }
   ll ans=0;
   if(x<n)
   {
       if(a[x][y]>c) ans+=(dfs(x+1,y,num+1,a[x][y]))%mod;
       ans%=mod;
       ans+=(dfs(x+1,y,num,c))%mod;
       ans%=mod;
   }
   if(y<m)
   {
       if(a[x][y]>c) ans+=(dfs(x,y+1,num+1,a[x][y]))%mod;
        ans%=mod;
       ans+=(dfs(x,y+1,num,c))%mod;
       ans%=mod;
   }

    return dp[x][y][num][c+1]=ans;
}
int main()
{
   while(~scanf("%d %d %d",&n,&m,&kk))
   {
       memset(dp,-1,sizeof(dp));
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m;j++)
           {
               scanf("%d",&a[i][j]);
           }
       }
     printf("%lld\n",dfs(1,1,0,-1));//注意这里要初始为-1
   }
    return 0;
}
dfs记忆化搜索
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 1000000007
#define N 55
int n,m,kk;
int a[N][N];
ll dp[N][N][13][13];

int main()
{
   while(~scanf("%d %d %d",&n,&m,&kk))
   {
       memset(a,0,sizeof(a));
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
       }
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m;j++)
           {
               for(int k=0;k<=kk;k++)
               {
                   for(int c=0;c<13;c++)
                   {
                       ll na=0,buna=0;
                        if(i==1&&j==1){
            if(!k||(k==1&&c>a[i][j]))dp[i][j][k][c]=1;
            continue;
        }
        if(k&&c>a[i][j])na=dp[i-1][j][k-1][a[i][j]]+dp[i][j-1][k-1][a[i][j]];
        buna=dp[i-1][j][k][c]+dp[i][j-1][k][c];
        dp[i][j][k][c]=na+buna;
        dp[i][j][k][c]%=mod;
                   }
               }
           }
       }
       printf("%lld\n",dp[n][m][kk][12]);
   }
    return 0;
}
dp

 

 


posted @ 2019-02-08 19:49  better46  阅读(239)  评论(0编辑  收藏  举报