POI2008UCI-The Great Escape

dp #POI #Year2008

倒着跑这个过程,发现为每次拓宽一个矩形,记录这个矩形的对角的坐标,当前的方向,可以得到 \(dp_{x_1,y_1,x_2,y_2,4}\) ,从同方向相邻的点,或者转向后经过一条边长的点转移过来,单次转移是 \(\mathcal{O}(1)\)

但是这个会 \(MLE\) ,考虑一般的优化方法,即滚动

因为统计答案需要第 \(1,4\) 维,所以考虑对第 \(2\) 维滚动掉

然后分讨转移 这个分讨实在恶心

// Author: xiaruize
const int INF = 0x3f3f3f3f3f3f3f3f;
int MOD;
const int N = 2e5 + 10;

void add(int &x, int y)
{
	x += y;
	x = (x % MOD + MOD) % MOD;
	// if (x >= MOD)
	// 	x -= MOD;
}

int n, m, x, y;
int dp[105][2][105][105][4];
char s[105][105];
int col[105][105], rw[105][105];

void solve()
{
	cin >> n >> m >> MOD >> y >> x;
	rep(i, 1, n) cin >> (s[i] + 1);
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			col[i][j] = col[i - 1][j] + (s[i][j] == '*');
			rw[i][j] = rw[i][j - 1] + (s[i][j] == '*');
		}
	}
	rep(i, 0, 3) dp[x][y & 1][x][y][i] = 1;
	per(y1, y, 1)
	{
		rep(x1, 1, n)
		{
			rep(x2, 1, n)
			{
				rep(y2, 1, m)
				{
					rep(i, 0, 3)
						dp[x1][(y1 & 1) ^ 1][x2][y2][i] = 0;
				}
			}
		}
		per(x1, x, 1)
		{
			rep(x2, x, n)
			{
				rep(y2, y, m)
				{
					if (x1 > 1 && s[x1 - 1][y2] == '+')
					{
						add(dp[x1 - 1][y1 & 1][x2][y2][2], dp[x1][y1 & 1][x2][y2][2]);
						if (rw[x1 - 1][y1 - 1] == rw[x1 - 1][y2])
							add(dp[x1 - 1][y1 & 1][x2][y2][3], dp[x1][y1 & 1][x2][y2][2]);
					}
					if (y1 > 1 && s[x1][y1 - 1] == '+')
					{
						add(dp[x1][(y1 & 1) ^ 1][x2][y2][3], dp[x1][y1 & 1][x2][y2][3]);
						if (col[x1 - 1][y1 - 1] == col[x2][y1 - 1])
							add(dp[x1][(y1 & 1) ^ 1][x2][y2][0], dp[x1][y1 & 1][x2][y2][3]);
					}
					if (x2 < n && s[x2 + 1][y1] == '+')
					{
						add(dp[x1][y1 & 1][x2 + 1][y2][0], dp[x1][y1 & 1][x2][y2][0]);
						if (rw[x2 + 1][y1 - 1] == rw[x2 + 1][y2])
							add(dp[x1][y1 & 1][x2 + 1][y2][1], dp[x1][y1 & 1][x2][y2][0]);
					}
					if (y2 < m && s[x2][y2 + 1] == '+')
					{
						add(dp[x1][y1 & 1][x2][y2 + 1][1], dp[x1][y1 & 1][x2][y2][1]);
						if (col[x1 - 1][y2 + 1] == col[x2][y2 + 1])
							add(dp[x1][y1 & 1][x2][y2 + 1][2], dp[x1][y1 & 1][x2][y2][1]);
					}
				}
			}
		}
	}
	// debug(dp);
	int res = 0;
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			add(res, dp[i][1][n][j][0]);
		}
	}
	cout << res << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}
posted @ 2024-04-15 19:41  xiaruize  阅读(5)  评论(0)    收藏  举报