C++-蓝桥杯-地宫取宝[2014真题][记忆化搜索]
一开始想的是dp四维状态都设好了,然后写起来贼恶心
然后改搜索,四类分支都想好了,但是复杂度又不对?
放弃后,看题解,艹,还真是两者结合起来,记忆化搜索。
好吧,不愧是你,蓝桥杯,这么喜欢暴力算法!
PS:
对于一个搜索状态,其返回值可能为0,所以数组初值要赋为-1
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int MOD=1e9+7; 6 int n,m,k; 7 int v[55][55]; 8 int f[55][55][15][15]; 9 int dfs(int x,int y,int num,int max){ 10 if(f[x][y][num][max+1]!=-1)return f[x][y][num][max+1]; 11 if(x==n&&y==m)return f[x][y][num][max+1]=(num==k||(num==k-1&&max<v[x][y])); 12 int ans=0; 13 if(x+1<=n){ 14 if(max<v[x][y])ans=(ans+dfs(x+1,y,num+1,v[x][y]))%MOD; 15 ans=(ans+dfs(x+1,y,num,max))%MOD; 16 } 17 if(y+1<=m){ 18 if(max<v[x][y])ans=(ans+dfs(x,y+1,num+1,v[x][y]))%MOD; 19 ans=(ans+dfs(x,y+1,num,max))%MOD; 20 } 21 return f[x][y][num][max+1]=ans; 22 } 23 int main() { 24 cin>>n>>m>>k; 25 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>v[i][j]; 26 memset(f,-1,sizeof(f));dfs(1,1,0,-1); 27 cout<<f[1][1][0][0]<<endl; 28 return 0; 29 }
以上是普遍流传的版本,但是对于类似dp的搜索我喜欢从后往前搜索
代码略有不同,但是似乎更快,0msAC,空间也更小!?
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int MOD=1e9+7; 6 int n,m,k,v[55][55]; 7 int f[55][55][15][15]; 8 int dfs(int x,int y,int num,int max){ 9 if(f[x][y][num][max+1]!=-1)return f[x][y][num][max+1]; 10 if(x==1&&y==1)return f[x][y][num][max+1]=(num==0||(num==1&&v[1][1]<max)); 11 int ans=0; 12 if(x>1){ 13 if(v[x][y]<max)ans=(ans+dfs(x-1,y,num-1,v[x][y]))%MOD; 14 ans=(ans+dfs(x-1,y,num,max))%MOD; 15 } 16 if(y>1){ 17 if(v[x][y]<max)ans=(ans+dfs(x,y-1,num-1,v[x][y]))%MOD; 18 ans=(ans+dfs(x,y-1,num,max))%MOD; 19 } 20 return f[x][y][num][max+1]=ans; 21 } 22 int main(){ 23 cin>>n>>m>>k; 24 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>v[i][j]; 25 memset(f,-1,sizeof(f));cout<<dfs(n,m,k,15)<<endl; 26 return 0; 27 }
~~Jason_liu O(∩_∩)O