P6275 [USACO20OPEN]Sprinklers 2: Return of the Alfalfa P 輪廓線DP

youth518發表於2020-10-21

題意:

戳這裡檢視

分析:

我們可以通過手調樣例發現最後整張圖會沿著一條線分為兩個部分,所以我們利用這條分界線進行DP,我們設 f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0]表示現在在第 i i i行第 j j j列的格子右下角的點,0表示該向右延展,1表示向下擴充套件,每次方向變化時需要除以二,因為有一個原來可放可不放的格子不得不放,情況減少了,轉移的話看程式碼就能看懂

程式碼:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	const int maxn = 2005;
	const int mod = 1e9+7;
	const int inv2 = 500000004;
	bool vis[maxn][maxn];
	int f[maxn][maxn][2];
	int n,cnt=1;
	char ch[maxn];

	void work()
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%s",ch+1);
			for(int j=1;j<=n;j++)
			{
				if(ch[j]=='.')
				{
					vis[i][j]=true;
					cnt=cnt*2%mod;
				}
			}
		}
		f[1][0][1]=cnt;
		f[0][1][0]=cnt;
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=n;j++)
			{
				if(f[i][j][0])
				{
					f[i][j+1][0]=(f[i][j][0]+f[i][j+1][0])%mod;
					if(vis[i+1][j]) f[i+1][j][1]=(f[i+1][j][1]+(long long)f[i][j][0]*inv2%mod)%mod;
				}
				if(f[i][j][1])
				{
					f[i+1][j][1]=(f[i+1][j][1]+f[i][j][1])%mod;
					if(vis[i][j+1]) f[i][j+1][0]=(f[i][j+1][0]+(long long)f[i][j][1]*inv2%mod)%mod;
				}
			}
		}
		printf("%d\n",(f[n][n][0]+f[n][n][1])%mod);
	}

}

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

相關文章