(Memorization search) Blue Bridge Cup 2014 Provincial Competition C/C++ Group A Provincial Competition Zhenti 8 Treasures from the Underground Palace

topic

King X has an underground treasury. is a matrix of nxm lattices. Put one treasure in each cell. Each baby has a value sticker attached.

The entrance to the underground palace is in the upper left corner and the exit is in the lower right corner.

Xiao Ming was taken to the entrance of the underground palace, and the king asked him to walk only to the right or down.

When walking through a certain grid, if the value of the treasure in that grid is greater than that of any treasure in Xiao Ming's hand, Xiao Ming can pick it up (of course, he can also not take it).

When Xiaoming walks to the exit, if the treasures in his hand are exactly k, these treasures can be given to Xiaoming.

Please help Xiao Ming calculate how many different action plans he has to obtain these k treasures in a given situation.
Data format
  Enter a line of 3 integers, separated by spaces: nmk (1<=n,m<=50, 1<=k<=12)

Next, there are n rows of data, each row has m integers Ci (0<=Ci<=12) representing the value of the treasure on this grid

It is required to output an integer, indicating that exactly the number of action plans for k treasures is taken. The number can be large, print it modulo 1000000007.

For example, input:
  2 2 2
  1 2
  2 1
  The program should output:
  2

For another example, input:
  2 3 2
  1 2 3
  2 1 5
  The program should output:
  14

Resource convention:
  peak memory consumption < 256M
  CPU consumption < 1000ms

analyze

The question indicates that you can only go down or to the right. Here, go directly to bfs, go wherever you can, and try all the methods you can try. Here, you need to use memory search to store the previous state. Next time you need it When used directly, plus the restriction on k, it can be pruned

code section

Initialize a map, an array to store the state

int n,m,k;
int _map[60][60];	//地图 
int cache[51][51][14][14];

bfs part

In the pre-order, first determine whether the current state has been stored, if stored, use it directly, then determine the boundary conditions and k, and finally determine whether the last grid meets the requirements

The backtracking part, placed after the recursion, is used to record the calculated state

int bfs(int x,int y,int cnt,int maxv)
{
    
    
	//出口
	int ans=0;
	if(cache[x][y][cnt][maxv]!=-1)
		return cache[x][y][cnt][maxv];
		
	if(x==n||y==m||cnt>k)
		return 0;	
		
	if(x+1==n&&y+1==m)
	{
    
    
		if(cnt==k||(cnt+1==k&&_map[x][y]>maxv))
			ans++;
		return ans;
	}
		
			
	//现在能做的事情
	if(_map[x][y]>maxv)
	{
    
    
		ans+=bfs(x+1,y,cnt+1,_map[x][y]);
		ans+=bfs(x,y+1,cnt+1,_map[x][y]);
	} 
	ans+=bfs(x+1,y,cnt,maxv);
	ans+=bfs(x,y+1,cnt,maxv);
	
	cache[x][y][cnt][maxv]=ans;
	return cache[x][y][cnt][maxv];
}

full code

#include <bits/stdc++.h>
using namespace std;

int n,m,k;
int _map[60][60];	//地图 
int cache[51][51][14][14];

int bfs(int x,int y,int cnt,int maxv)
{
    
    
	//出口
	int ans=0;
	if(cache[x][y][cnt][maxv]!=-1)
		return cache[x][y][cnt][maxv];
		
	if(x==n||y==m||cnt>k)
		return 0;	
		
	if(x+1==n&&y+1==m)
	{
    
    
		if(cnt==k||(cnt+1==k&&_map[x][y]>maxv))
			ans++;
		return ans;
	}
		
			
	//现在能做的事情
	if(_map[x][y]>maxv)
	{
    
    
		ans+=bfs(x+1,y,cnt+1,_map[x][y]);
		ans+=bfs(x,y+1,cnt+1,_map[x][y]);
	} 
	ans+=bfs(x+1,y,cnt,maxv);
	ans+=bfs(x,y+1,cnt,maxv);
	
	cache[x][y][cnt][maxv]=ans;
	return cache[x][y][cnt][maxv];
}

int main (void)
{
    
    
	cin>>n>>m>>k;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>_map[i][j];
			
	memset(cache,-1,sizeof(cache));
	
	cout<<bfs(0,0,0,0);		
		
	return 0;
}

Summarize

When I was learning dynamic programming, I learned a little about memoization search. The teacher said that the time complexity of memoization search is difficult to estimate. It is about k times the time complexity of dynamic programming, but memoization search is easier to think about.

Guess you like

Origin blog.csdn.net/weixin_46035615/article/details/123893046