1. 程式人生 > >問題 1436: 地宮取寶 (dp)

問題 1436: 地宮取寶 (dp)

行數 地宮取寶 pan pen 行動 main spa span names

題目傳送門

時間限制: 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

 


問題 1436: 地宮取寶 (dp)