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;
}
标签:Great,y2,rep,POI2008UCI,y1,Escape,x2,x1,dp
From: https://www.cnblogs.com/xiaruize/p/18136782