CF348D LGV引理

题意:

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

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

分析:

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

前置芝士:LGV引理

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

不会可以戳这里

题目可以转化成2个起点:\((1,2),(2,1)\) 到 两个终点: \((n,m-1),(n-1,m)\)的不相交路径方案数,通过\(O(nm)\)\(DP\)可以预处理出每个起点到每个终点的路径个数,构造出一个大小为\(2\times 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\n",((x1*x4%mod)-(x2*x3%mod)+mod)%mod);
	}

}

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

posted @   youth518  阅读(93)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示