CF348D LGV引理

题意:

给定一张图,图上存在障碍点,两个人从((1,1))出发,只能向上或向右走,走到((n,m))且路径不相交的方案数

数据范围:(1le n,mle 3000)

分析:

没什么好分析的,就是个裸题

前置芝士:LGV引理

(LGV)引理就是求解(n)组一一对应的起点到终点,且路径不相交的方案数

不会可以戳这里

题目可以转化成2个起点:((1,2),(2,1)) 到 两个终点: ((n,m-1),(n-1,m))的不相交路径方案数,通过(O(nm))(DP)可以预处理出每个起点到每个终点的路径个数,构造出一个大小为(2 imes 2)(LGV)引理矩阵,然后直接求矩阵的行列式就可以了

代码:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	const int maxn = 3005;
	const long long mod = 1e9+7;
	long long f[maxn][maxn],x1,x2,x3,x4;
	bool mp[maxn][maxn];
	char ch[maxn];
	long long n,m;

	void work()
	{
		scanf("%lld%lld",&n,&m);
		for(int i=1;i<=n;i++)
		{
			scanf("%s",ch+1);
			for(int j=1;j<=m;j++)
			{
				if(ch[j]=='#')mp[i][j]=true;
			}
		}
		
		memset(f,0,sizeof(f));
		f[1][1]=1;
		for(int i=2;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(mp[i][j]) continue;
				f[i][j]=(f[i][j]+f[i-1][j]+f[i][j-1])%mod;
			}
		}
		x1=f[n][m-1];x2=f[n-1][m];
		
		memset(f,0,sizeof(f));
		f[1][1]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=2;j<=m;j++)
			{
				if(mp[i][j]) continue;
				f[i][j]=(f[i][j]+f[i-1][j]+f[i][j-1])%mod;
			}
		}
		x3=f[n][m-1];x4=f[n-1][m];
		
		printf("%lld
",((x1*x4%mod)-(x2*x3%mod)+mod)%mod);
	}

}

int main()
{
	zzc::work();
	return 0;
}

原文地址:https://www.cnblogs.com/youth518/p/13807032.html