Codeforces Gym 221682 W Grid Coloring(DP)

Problem W — limit 1 second
                                                                                     Grid Coloring
You have an m-by-n grid of squares that you wish to color. You may color each square either red
or blue, subject to the following constraints:
• Every square must be colored.
• Colors of some squares are already decided (red or blue), and cannot be changed.
• For each blue square, all squares in the rectangle from the top left of the grid to that square
must also be blue.
Given these constraints, how many distinct colorings of the grid are there? The grid cannot be

rotated.


Input
The first line of input consists of two space-separated integers m and n (1 ≤ m, n ≤ 30).
Each of the next m lines contains n characters, representing the grid. Character ‘B’ indicates
squares that are already colored blue. Similarly, ‘R’ indicates red squares. Character ‘.’ indicates

squares that are not colored yet.


Output
Print, on a single line, the number of distinct colorings possible.
For the first sample, the 6 ways are:

BB BB BR BB BR BR

BR BR BR BR BR RR

BB BR RR BB BB RR

23

Sample Input and Output

3 2
..
B.

.R                                                     6

7 6
......
.....B
.B..R.
......
...B..
.R....

...R..                                               3


2 2
R.
.B                                                    0


【思路】

題目給定一張可能某些格子已經被塗上藍色或紅色的方格圖,要求塗色方案書,塗色必須滿足所有藍色格左上方的格子全塗藍色,所有紅色格右下方的格子全塗紅色。

我們可以先處理這個圖,把已經上色的藍色格左上角都塗上,紅色格右下角也都塗上,剩下的空白格必定會落在右上到左下之間的區域。容易想到,整張圖塗完了以後會形成一條右上到左下的邊界。不同的塗色方案意味着這條邊界形狀不同,我們可以從上到下逐步維護邊界的信息以獲得最後答案。我們來從上到下、從左到右塗色,假設已經塗到了第i行第j列,設dp[i][j]是第i行第j列塗成藍色的方案數,那麼顯然,它塗成紅色的情況就被dp[i][j - 1]記錄了,所以只考慮把空白格塗爲藍色就夠了,因其上面的也只能是第j列到第m列是藍色的,於是可得轉移方程:dp[i][j] = sum(dp[i - 1][k]),其中j <= k <= m。

注意唯有含空格的行才能被塗色,若空格早被分割成右上和左下兩塊,我們就拿最後一個格記錄一下上一行的情況就好。初始時,第一個含有空格的行的被更新的格賦值爲1,最後由下而上第一個非零行的和即是答案。

有個坑點,若題目給的圖本身便不合法,輸出0,若給的圖已經被合法地塗滿了,輸出1


【代碼】

//************************************************************************
// File Name: W.cpp
// Author: Shili_Xu
// E-Mail: [email protected] 
// Created Time: 2018年03月21日 星期三 16時59分33秒
//************************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 35;

int n, m;
char gr[MAXN][MAXN];
int g[MAXN][MAXN];
unsigned long long dp[MAXN][MAXN];

int main()
{
	scanf("%d %d", &n, &m);
	char s[MAXN];
	for (int i = 1; i <= n; i++) {
		scanf("%s", s + 1);
		for (int j = 1; j <= m; j++) gr[i][j] = s[j];
	}
	bool flag = true;
	memset(g, 0, sizeof(g));
	for (int i = 1; i <= n && flag; i++) {
		for (int j = 1; j <= m && flag; j++) {
			if (gr[i][j] == 'B') {
				for (int l = 1; l <= i; l++)
					for (int c = 1; c <= j; c++) g[l][c] = 1;
			}
			if (gr[i][j] == 'R') {
				for (int l = i; l <= n; l++)
					for (int c = j; c <= m; c++) {
						if (gr[l][c] == 'B') flag = false;
						g[l][c] = 2;
					}
			}
		}
	}
	if (!flag) {
		printf("0");
		return 0;
	}
	memset(dp, 0, sizeof(dp));
	for (int i = 1; i <= n; i++) {
		int st = -1, ed;
		for (int j = 1; j <= m; j++) {
			if (!g[i][j] && st == -1) st = j - 1;
			if (st != -1)  {
				if (g[i][j]) {
					ed = j - 1;
					break;
				}
				if (j == m) ed = j;
			}
		}
		if (st != -1) {
			for (int j = st; j <= ed; j++) {
				for (int k = j; k <= m; k++) dp[i][j] += dp[i - 1][k];
				if (!dp[i][j]) dp[i][j] = 1;
			}
		}
		else {
			for (int j = 0; j <= m; j++) dp[i][m] += dp[i - 1][j];
		}
	}
	unsigned long long ans = 0;
	for (int l = n; l >= 1; l--) {
		for (int i = 0; i <= m; i++) ans += dp[l][i];
		if (ans) break;
	}
	printf("%llu", (ans > 0 ? ans : 1));
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章