1814: Ural 1519 Formula 1
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 879 Solved: 328
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
**..
....
....
....
Sample Output
2
HINT
Source
插頭DP比起其他DP還真的是骨(dai)骼(ma)精(ju)奇(chang)啊... 不過能想到插頭這樣一個很好的比喻還是非常6. cdq的講稿非常清晰, 可惜萬惡的百度文庫需要1下載券... 搞得我花掉了我(b)自(f)己(k)的一個下載券... 這裏附上一個同樣清晰明瞭的講解: 插頭DP——從不會到崩潰. 說着崩潰講的還是很好的嘛~ 但是確實噁心. 省選考到我就gg(flag). 這道題就是裸題啦~
#include<bits/stdc++.h>
#define clear(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long lnt;
const int maxn = 2e5 + 5;
char s[15];
lnt ans, dp[2][maxn];
int n, m, c, cnt, ex, ey, tot[2], bit[20];
int mp[15][15], h[maxn], sta[2][maxn];
struct edge{int nxt, v;}e[maxn];
inline void insert(const int &s, const lnt &num) {
int u = s % maxn;
for (int i = h[u]; i; i = e[i].nxt)
if (sta[c][e[i].v] == s) {
dp[c][e[i].v] += num;
return;
}
e[++ cnt].v = ++ tot[c];
e[cnt].nxt = h[u], h[u] = cnt;
sta[c][tot[c]] = s, dp[c][tot[c]] = num;
}
inline void Plug_Dp() {
tot[0] = 1, dp[c][1] = 1;
register int i, j, k, t;
for (i = 1; i <= n; ++ i) {
for (j = 1; j <= tot[c]; ++ j)
sta[c][j] <<= 2;
for (j = 1; j <= m; ++ j) {
clear(h), cnt = 0;
c ^= 1, tot[c] = 0;
for (k = 1; k <= tot[c ^ 1]; ++ k) {
int s = sta[c ^ 1][k];
lnt num = dp[c ^ 1][k];
int p = (s >> bit[j - 1]) & 3;
int q = (s >> bit[j]) & 3;
if (!mp[i][j]) {
if (!p && !q) insert(s, num);
}
else if (!p && !q) {
if (!mp[i + 1][j] || !mp[i][j + 1]) continue;
s += (1 << bit[j - 1]) + (1 << (bit[j] + 1));
//左括號是0, 右括號是1, 四進制在二進制下兩位表示一字節
insert(s, num);
}
else if (!p && q) {
if (mp[i][j + 1]) insert(s, num);
if (mp[i + 1][j]) {
s += (1 << bit[j - 1]) * q - (1 << bit[j]) * q;
insert(s, num);
}
}
else if (p && !q) {
if (mp[i + 1][j]) insert(s, num);
if (mp[i][j + 1]) {
s += (1 << bit[j]) * p - (1 << bit[j - 1]) * p;
insert(s, num);
}
}
else if (p + q == 2) {
int b = 1;
for (t = j + 1; t <= m; ++ t) {
int v = (s >> bit[t]) & 3;
if (v == 1) b ++; //根據括號序列的性質
if (v == 2) b --;
if (!b) {
s -= (1 << bit[t]);
break;
}
}
s -= (1 << bit[j - 1]) + (1 << bit[j]);
insert(s, num);
}
else if (p + q == 4) {
int b = 1;
for (t = j - 2; ~t; -- t) {
int v = (s >> bit[t]) & 3;
if (v == 2) b ++;
if (v == 1) b --;
if (!b) {
s += (1 << bit[t]);
break;
}
}
s -= (1 << (bit[j - 1] + 1)) + (1 << (bit[j] + 1));
insert(s, num);
}
else if (p == 2 && q == 1) {
s -= (1 << (bit[j - 1] + 1)) + (1 << bit[j]);
insert(s, num);
}
else if (p == 1 && q == 2) {
if (i == ex && j == ey) ans += num;
}
}
}
}
printf("%lld\n", ans);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < 26; ++ i)
bit[i] = i << 1;
for (int i = 1; i <= n; ++ i) {
scanf("%s", s + 1);
for (int j = 1; j <= m; ++ j)
if (s[j] == '.') mp[i][j] = 1, ex = i, ey = j;
}
Plug_Dp();
return 0;
}