BZOJ2331: [SCOI2011]地板

題面

題意

給出一張地圖,請用“L”形地板覆蓋所有非障礙的格子,“L”可以旋轉,但兩邊的長度都必須大於0。

做法

因爲數據範圍非常小,所以可以用插頭dp。
對於插頭我們記錄三種狀態:
0:沒有插頭。
1:有插頭,且是未拐過彎的“L”。
2:有插頭,且是拐過彎的“L”。
然後在轉移時分3*3=9種情況分別轉移,有點耐心就好了。

代碼

#include<iostream>
#include<cstdio>
#include<vector>
#define ll long long
#define N 110
#define M 20110520
using namespace std;

ll m,n,num,dp[2][200100],san[N],ans,li,lj;
char str[N];
bool mm[N][N],now,cur;
vector<ll>have[2];

inline ll get(ll u,ll v){return u/san[v-1]%3;}
inline ll chg(ll u,ll v,ll w){return u+(w-get(u,v))*san[v-1];}
inline void in(ll u)
{
	if(!dp[now][u]) have[now].push_back(u);
	dp[now][u]+=num;
	if(dp[now][u]>M) dp[now][u]-=M;
}

int main()
{
	ll i,j,k,t,p,q,kk;
	cin>>m>>n;
	for(i=1;i<=m;i++)
	{
		scanf("%s",str+1);
		for(j=1;j<=n;j++)
		{
			if(m<n) mm[j][i]=(str[j]=='*');
			else mm[i][j]=(str[j]=='*');
		}
	}
	if(m<n) swap(m,n);
	for(i=1;i<=m;i++) mm[i][0]=mm[i][n+1]=1;
	for(i=0;i<=n+1;i++) mm[0][i]=mm[m+1][i]=1;
	now=san[0]=num=1;
	for(i=1;i<=n+1;i++) san[i]=san[i-1]*3;
	in(0);
	for(i=1;i<=m;i++)
	{
		for(j=1;j<=n;j++)
		{
			swap(now,cur);
			have[now].clear();
			for(kk=0;kk<have[cur].size();kk++)
			{
				k=have[cur][kk];
				p=get(k,j),q=get(k,j+1);
				t=chg(k,j,0),t=chg(t,j+1,0);
				num=dp[cur][k];
				if(mm[i][j]) in(k);
				else if(!p&&!q)
				{
					if(!mm[i][j+1]) in(chg(k,j+1,1));
					if(!mm[i+1][j]) in(chg(k,j,1));
					if(!mm[i][j+1]&&!mm[i+1][j])
					{
						t=chg(k,j,2),t=chg(t,j+1,2);
						in(t);
					}
				}
				else if(!p&&q==1)
				{
					if(!mm[i+1][j]) in(chg(t,j,1));
					if(!mm[i][j+1]) in(chg(k,j+1,2));
				}
				else if(!p&&q==2)
				{
					in(t);
					if(!mm[i+1][j]) in(chg(t,j,2));
				}
				else if(p==1&&!q)
				{
					if(!mm[i+1][j]) in(chg(k,j,2));
					if(!mm[i][j+1]) in(chg(t,j+1,1));
				}
				else if(p==1&&q==1) in(t);
				else if(p==2&&!q)
				{
					in(t);
					if(!mm[i][j+1]) in(chg(t,j+1,2));
				}
				dp[cur][k]=0;
			}
		}
		swap(now,cur);
		have[now].clear();
		for(kk=0;kk<have[cur].size();kk++)
		{
			k=have[cur][kk];
			num=dp[cur][k];
			in(k*3);
			dp[cur][k]=0;
		}
	}
	cout<<dp[now][have[now][0]];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章