(动态规划)Educational Codeforces Round 107 (Rated for Div. 2) E. Colorings and Dominoes

题目:
https://codeforces.ml/contest/1511/problem/E
You have a large rectangular board which is divided into n×m cells (the board has n rows and m columns). Each cell is either white or black.

You paint each white cell either red or blue. Obviously, the number of different ways to paint them is 2w, where w is the number of white cells.

After painting the white cells of the board, you want to place the maximum number of dominoes on it, according to the following rules:

  • each domino covers two adjacent cells;
  • each cell is covered by at most one domino;
  • if a domino is placed horizontally (it covers two adjacent cells in one of the rows), it should cover only red cells;
  • if a domino is placed vertically (it covers two adjacent cells in one of the columns), it should cover only blue cells.

Let the value of the board be the maximum number of dominoes you can place. Calculate the sum of values of the board over all 2w possible ways to paint it. Since it can be huge, print it modulo 998244353.

Input
The first line contains two integers n and m (1≤n,m≤3⋅105; nm≤3⋅105) — the number of rows and columns, respectively.

Then n lines follow, each line contains a string of m characters. The j-th character in the i-th string is * if the j-th cell in the i-th row is black; otherwise, that character is o.

Output
Print one integer — the sum of values of the board over all 2w possible ways to paint it, taken modulo 998244353.

Input

3 4
**oo
oo*o
**oo

Output

144

Input

3 4
**oo
oo**
**oo

Output

48

Input

2 2
oo
o*

Output

4

Input

1 4
oooo

Output

9

思路:
可以把问题拆分成求每行每列相邻的 ‘o’ 的可以放置的domino的数量的和。
设dp [ i ]是 i个相邻的 ‘o’ 的可以放置的domino的数量,那么,
dp [ i ] = dp [ i - 2] * 2 + dp [ i - 1] + 2 ^ (i - 2)
在这里插入图片描述每个相邻的 'o’的可以放置的domino的数量产生的贡献 = dp [ i ] * 2 ^ ( ‘0’ 的总个数 - i)

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 3e5 + 10;
const ll MOD = 998244353;
string s[MAXN];
ll pow2[MAXN], dp[MAXN];
int main(){
    
    
	ios_base::sync_with_stdio(false), cin.tie(0);
	int n, m;
	int cnt = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++){
    
    
		cin >> s[i];
		for (int j = 0; j < m; j++)
			if (s[i][j] == 'o')
				cnt++;
	}
	dp[2] = pow2[0] = 1;
	for (int i = 1; i <= cnt; i++)
		pow2[i] = (pow2[i-1] << 1) % MOD;
	for (int i = 3; i <= cnt; i++)
		dp[i] = (dp[i-1] + (dp[i-2] << 1) + pow2[i-2]) % MOD;
	ll ans = 0, temp;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			if (s[i][j] == 'o'){
    
    
				temp = 1;
				while (++j < m && s[i][j] == 'o')
					temp++;
				if (temp >= 2)
					ans = (ans + dp[temp] * pow2[cnt-temp]) % MOD;
			}
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			if (s[j][i] == 'o'){
    
    
				temp = 1;
				while (++j < n && s[j][i] == 'o')
					temp++;
				if (temp >= 2)
					ans = (ans + dp[temp] * pow2[cnt-temp]) % MOD;
			}
	cout << ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ymxyld/article/details/115914569