blog

「青い橋の杯」深さ優先探索 - 大地の宮殿での宝探し

ダンジョンの宝物庫はn x mのグリッドの行列です。各グリッドには宝が1つあります。各宝物には値が付けられています。ダンジョンの入り口は左上にあり、出口は右下にあります。 明は地下宮殿の入り口に連れて...

Aug 6, 2020 · 2 min. read
シェア

説明

ダンジョンには宝物庫があります。各マスには宝が1つずつ入っています。各宝物には値が付いています。ダンジョンの入り口は左上、出口は右下です。明は地下宮殿の入り口に連れて行かれ、王様から右か下にしか歩かないように言われます。あるマス目を通り抜けたとき、そのマス目にある宝物の価値が、明の手にある宝物の価値よりも高ければ、明はその宝物を拾うことができます。明が出口にたどり着いたとき、明の手の中にちょうどK個の宝物があれば、明に渡すことができます。与えられた状況でk個の宝物を手に入れるために、Mingはいくつの異なる行動をとることができるかを考えてください。

データ形式

空白で区切られた3つの整数の行を入力してください: n m k . 次にn行のデータがあり、それぞれm個の整数Ciでこのグリッド上の宝物の値を表します。

ちょうどk個の宝物を取るための行動コースの数を表す整数を出力してもらいます。この数は大きいかもしれないので、1000000007でモデル化した結果を出力してください。

例えば、入力する:
2 2 2
1 2
2 1
プログラムは出力すべきである:
2
再び、例えば、入力する:
2 3 2
1 2 3
2 1 5
プログラムは出力すべきである:
14

コードの実装:

#include <iostream>
#include<cstring>
using namespace std;
const int MAX=55;
const int K=15;
const int MOD=1000000007;
int n,m,k;
int map[MAX][MAX];
int dp[MAX][MAX][K][K];
/*dp[x][y][num][max]=nx,yの位置にいるとき、手に持っている宝物の総数を表す。
最も大きな値を持つものをmaxとし、この位置から終点までのフェッチ方法はn通りある*/ 
int dfs(int x,int y,int num,int maxValue)
{
 if(dp[x][y][num][maxValue+1]!=-1)
 return dp[x][y][num][maxValue+1];
 if(x==n && y==m){
 if(num==k || num==k-1&&map[x][y]>maxValue)
 return 1;
 return 0;
 }
 long long sum=0;
 if(x+1<=n){
 if(map[x][y]>maxValue)
 sum+=dfs(x+1,y,num+1,map[x][y]);
 sum+=dfs(x+1,y,num,maxValue);
 }
 if(y+1<=m){
 if(map[x][y]>maxValue)
 sum+=dfs(x,y+1,num+1,map[x][y]);
 sum+=dfs(x,y+1,num,maxValue);
 }
 return dp[x][y][num][maxValue+1]=sum%MOD;
}
int main() {
 cin>>n>>m>>k;
 for(int i=1;i<=n;i++)
 for(int j=1;j<=m;j++)
 cin>>map[i][j];
 memset(dp,-1,sizeof(dp));
 dfs(1,1,0,-1);
 cout<<dp[1][1][0][0]<<endl;
 return 0;
}
Read next

javascriptのベスト・プラクティス:パフォーマンスの最適化、コーディング・プラクティスなどを含む。

関数とメソッド:このような関数の目的やタスクを完了するために使用することができるアルゴリズムなど。 ハック:特殊なハックの断片がどのように作られているかを説明します。 変数型の透明性:例えば、指定された変数型を初期化する、ハンガリー語のマークアップ、指定された型に対する型アノテーションなど。 デカップリング(Decoupling)スタイルを直接操作しないようにすること。

Aug 6, 2020 · 4 min read