0
点赞
收藏
分享

微信扫一扫

2019南京-Digital Path-(记忆化搜索转化为拓扑dp+dp的本质理解)

慕容冲_a4b8 2022-03-13 阅读 17

Digital Path

题意:
就是给你一个二维数组,让你找出有多少路径。这个路径的条件是,必须上下左右,必须权值一个一个的增加,必须长度>=4,而且不能再扩展了。输出答案,同时对1e9+7取模。

思考:
刚看到其实我以为是个比较难的题,其实呢就是给你一些条件,让你找合法路径。很明显在二维数组里面的事情,一般都是记忆化搜索之类的,就像这道题:滑雪。但是呢,一般记忆化搜索呢细节会多一些,而且不容易调试。其实我们知道记忆化搜索的本质也是dp。dp的本质呢其实就是在有向无环图中的迭代更新,从所有的初始状态最终达到终点状态。所以呢,如果我们能把这个题目的图建立出来,这道题就简单了,但是建图你要保证,这个图建立出来一定不会包含环。直接拓扑的同时维护更新答案就ok了。

代码:

本题代码:

int T,n,m,k;
int va[M][M];
int in[M][M],out[M][M];
int dp[M][M][5]; //走到ij点,长度为1,2,3,大于等于4。

int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

void topsort()
{
	queue<PII > q;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(in[i][j]==0)
			{
				q.push({i,j});
				dp[i][j][1] = 1;
			}
		}
	}
	while(q.size())
	{
		auto now = q.front();
		q.pop();
		int x = now.fi,y = now.se;
		for(int i=0;i<4;i++)
		{
			int xx = x+dx[i],yy = y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m) continue;
			if(va[xx][yy]==va[x][y]+1) //如果可以走过来
			{
				dp[xx][yy][2] = (dp[xx][yy][2]+dp[x][y][1])%mod;
				dp[xx][yy][3] = (dp[xx][yy][3]+dp[x][y][2])%mod;
				dp[xx][yy][4] = (dp[xx][yy][4]+dp[x][y][3]+dp[x][y][4])%mod; //>=4的可以从3的和4的过来
				if(--in[xx][yy]==0) q.push({xx,yy});
			}
		}
	}
}

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		cin>>va[i][j];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int k=0;k<4;k++)
			{
				int x = i+dx[k],y = j+dy[k];
				if(x>=1&&x<=n&&y>=1&&y<=m) //为了不会重复加,当枚举到ij的时候,我们只看他到底会怎么样
				{
					if(va[i][j]+1==va[x][y]) out[i][j]++;
					if(va[i][j]-1==va[x][y]) in[i][j]++;
				}
			}
		}
	}
	topsort();
	int ans = 0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		if(out[i][j]==0) ans = (ans+dp[i][j][4])%mod;
	}
	cout<<ans%mod;
	return 0;
}

滑雪代码:
int T,n,m,k;
int va[M][M];
int dp[M][M];
int in[M][M],out[M][M];

int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

void topsort()
{
	queue<PII > q; 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(in[i][j]==0)
			{
				q.push({i,j});
				dp[i][j] = 1;
			}
		}
	}
	while(q.size())
	{
		auto now = q.front();
		q.pop();
		int x = now.fi,y = now.se;
		for(int i=0;i<4;i++)
		{
			int xx = x+dx[i],yy = y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m) continue;
			if(va[xx][yy]<va[x][y])
			{
				dp[xx][yy] = max(dp[xx][yy],dp[x][y]+1);
				if(--in[xx][yy]==0) q.push({xx,yy});
			}
		}
	}
}

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		cin>>va[i][j];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=0;k<4;k++)
			{
				int x = i+dx[k],y = j+dy[k];
				if(x<1||x>n||y<1||y>m) continue;
				if(va[i][j]>va[x][y]) out[i][j]++;
				if(va[i][j]<va[x][y]) in[i][j]++;
			}
		}
	}
	topsort();
	int maxn = 1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		maxn = max(maxn,dp[i][j]);
	}
	cout<<maxn;
	return 0;
}

总结:
多多理解算法的本质。

举报

相关推荐

0 条评论