HDU 6416 2018HDU多校賽 第九場 Rikka with Seam(dp + 字首和優化)
阿新 • • 發佈:2019-02-06
大致題意:給你一個n*m的01矩陣,現在要讓你每一行和每一列都去掉一個數字,而且要求相鄰兩行之間去掉數字的位置的絕對值要小於等於k。現在問你刪除之後的矩形最多有幾種。
首先,我們一行一行考慮,對於同一行,顯然是看有多少個塊,有多少個塊就有多少個方案。然後對於整個矩陣來說,任意位置(i,j)可以從上一行的(j-k,j+k)之間轉移過來。dp[i][j]表示不考慮重複的情況下,處理到第i行,且第i行刪掉第j個位置的方案數。那麼,顯然根據之前說的轉移區間,有轉移方程:
但是,這裡面會有重複,因為一塊裡面刪掉任意一個都是一樣的。所以我們考慮要刪掉這些計算重複的。那麼這重複的具體來說是多少呢?我們不妨設重複的為ss[i][j],表示第i行第j個位置,與其同一行的第j-1個位置重複的部分。我們考慮,兩個相鄰的位置j和j-1的相交區間是[j-k,j-1+k],於是我們這個ss[i][j]也要從上一行的這一個區間轉移過來,當然了,還要保證j和j-1要在同一個塊,否則j和j-1是不會有重複的。具體來說:
這樣,我們就解決的這個問題,對於位置(i,j)來說,處理到第i行,且第i行刪掉j的方案數就是dp[i][j]-ss[i][j]。
這個dp暴力的話,時間複雜度是O(N^3)的,但是這個顯然是可以用字首和優化一下。如此複雜度可以到O(N^2),然後為了節省空間,我的程式碼裡面用了滾動陣列。具體見程式碼:
#include<bits/stdc++.h> #define LL long long #define mod 998244353 #define pb push_back #define lb lower_bound #define ub upper_bound #define INF 0x3f3f3f3f #define sf(x) scanf("%d",&x) #define sc(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr(x,n) memset(x,0,sizeof(x[0])*(n+5)) #define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) #define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) using namespace std; const int N = 2e3 + 10; int ss[2][N],s[2][N]; char str[N][N]; int main() { int T; sf(T); while(T--) { int n,m,k; sc(n,m,k); for(int i=1;i<=n;i++) { str[i][0]='9'; scanf("%s",str[i]+1); } int cur=1,pre=0; clr(s[pre],m); clr(ss[pre],m); for(int i=1;i<=m;i++) { s[0][i]=1; ss[0][i]=(str[1][i]==str[1][i-1]); } for(int i=2;i<=n;i++) { clr(ss[cur],m); clr(s[cur],m); for(int j=1;j<=m;j++) { s[pre][j]=(s[pre][j-1]+s[pre][j])%mod; ss[pre][j]=(ss[pre][j-1]+ss[pre][j])%mod; } for(int j=1;j<=m;j++) { int l=max(1,j-k),r=min(m,j+k); s[cur][j]=(s[pre][r]-s[pre][l-1]+mod)%mod; s[cur][j]=(s[cur][j]-(ss[pre][r]-ss[pre][l]+mod)%mod+mod)%mod; if (str[i][j]!=str[i][j-1]) {ss[cur][j]=0;continue;} r=min(m,j+k-1); ss[cur][j]=(s[pre][r]-s[pre][l-1]+mod)%mod; ss[cur][j]=(ss[cur][j]-(ss[pre][r]-ss[pre][l]+mod)%mod+mod)%mod; } swap(cur,pre); } LL ans=s[pre][1]%mod; for(int i=2;i<=m;i++) ans=(ans+s[pre][i]-ss[pre][i]+mod)%mod; printf("%lld\n",ans); } return 0; }