D. Treasure Island(dp+双模数)

, 首先是数据范围,只能开一维数组模拟二维数组

2 , 然后答案最坏是2,因为可以在起点两边堵住

( 1 , 1 ) ( n , m ) 0 若不能从(1,1)到(n,m)答案是0

1 使 ( 1 , 1 ) ( n , m ) 否则答案为1的情况就是存在某个点使得是(1,1)到(n,m)的必经之路

d p 考虑dp

d p [ i ] [ j ] ( 1 , 1 ) ( i , j ) , f [ i ] [ j ] ( n , m ) ( i , j ) dp[i][j]表示从(1,1)到(i,j)的方案,f[i][j]表示从(n,m)到(i,j)的方案

( 1 , 1 ) ( n , m ) d p [ n ] [ m ] 由于(1,1)到(n,m)的方案有dp[n][m]种

( i , j ) d p [ i ] [ j ] f [ i ] [ j ] 而经过点(i,j)的路径有dp[i][j]*f[i][j]种

那么比较是否相等即可

, ( , ) 但是注意取模,必须用双模数(我第一次双模数都被卡了,质数选择很关键)

尽量选不常用的质数

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1000005;
const int mmod=1e9+333+7;
int n,m,dp[1000009],f[1000009],ddp[1000009],ff[1000009];
char a[1000009];
signed main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++) 
		cin >> a[(i-1)*m+j];
	dp[n*m]=1,ddp[n*m]=1;
	for(int i=n;i>=1;i--)
	for(int j=m;j>=1;j--)
	{
		if( i==n&&j==m )	continue;
		int now=(i-1)*m+j;
		int l=i*m+j,r=(i-1)*m+j+1;
		if( a[now]=='#' )	continue;
		if( j!=m )	dp[now]+=dp[r],ddp[now]+=ddp[r];
		if( i!=n )	dp[now]+=dp[l],ddp[now]+=ddp[l];
		dp[now]%=mod,ddp[now]%=mmod;
	}
	f[1]=1; ff[1]=1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		if( i==1&&j==1 )	continue;
		int now=(i-1)*m+j;
		int l=(i-2)*m+j,r=(i-1)*m+j-1;
		if( a[now]=='#' )	continue;
		if( j!=1 )	f[now]+=f[r],ff[now]+=ff[r];
		if( i!=1 )	f[now]+=f[l],ff[now]+=ff[l];
		f[now]%=mod,ff[now]%=mmod; 		
	}
	if( f[n*m]==0&&ff[n*m]==0 )//一开始就到不了啊 
	{
		cout << 0;
		return 0;
	}
	int flag=0;
	for(int i=2;i<=n*m-1;i++)
		if( (dp[i]*f[i]%mod==dp[1] )&&(ddp[i]*ff[i]%mmod==ddp[1]) )	flag=1;//是必经之路
	if( flag )	cout << 1;
	else	cout << 2; 
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107725258
今日推荐