1. 程式人生 > >Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

bitset typedef src order esp red memset return sizeof

題目傳送門

題目大意:

給出n*m的網格,有紅藍兩種顏色,每個格子都必須被染色,當一個格子被染成藍色後,這個格子左上方的一塊都必須被染成藍色,問最後的方案數量。

思路:

按照題目條件,如果有一個格子被染成了紅色,則這個格子的右下方要全部被染成紅色,也就是這個給出的網格能讓我們染色的,是一個左上方和右下方都是階梯型的圖形,而對於每一行來說,當一個格子被染成了藍色,那麽左邊的所有格子都必須被染成藍色,所以我們設 f[ i ][ j ] 表示第 i 行 第 j 個格子被染成藍色的方案數量,那麽這個dp方程就是 f[ i ][ j ] += f[ i+1 ][ k ](0<=k<=m)。

而對於每一行,我們可以預處理出這一行的能填藍色的左右邊界,最下面一行能填顏色的賦值為1(註意,f [ n ][ 0 ]也要賦值,這表示這一行全填為紅色)。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<unordered_map>
#define
CLR(a,b) memset((a),(b),sizeof((a))) using namespace std; typedef long long ll; inline int rd() { int f = 1; int x = 0; char s = getchar(); while (s<0 || s>9) {if (s == -)f = -1;s = getchar();} while (s >= 0&&s <= 9) {x = x * 10 + s - 0;s = getchar();} x
*= f;return x;} inline ll gcd(ll a, ll b) { if (b == 0)return a; return gcd(b, a%b); } int n,m; char mp[40][40]; int l[40],r[40]; ll f[40][40]; int flag=0; int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%s",mp[i]+1); l[i]=0,r[i]=m; for(int j=1; j<=m; j++) { if(mp[i][j]==B) l[i]=max(l[i], j ); if(mp[i][j]==R) r[i]=min(r[i], j - 1); } if(r[i]<l[i])flag=1; } if(flag) { printf("0\n"); return 0; } for(int i=l[n]; i<=r[n]; i++) { f[n][i]=1; } for(int i=n-1; i>=1; i--) { for(int j=l[i]; j<=r[i]; j++) { for(int k=l[i+1]; k<=r[i+1]&&k<=j; k++) { f[i][j]+=f[i+1][k]; } } } ll sum=0; for(int i=0; i<=m; i++)sum+=f[1][i]; printf("%lld\n",sum); }
View Code

Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)