以前一直被【jyltxdztysdtgh】嚇到,雖然cdq的論文看的懂,但一直沒有寫,太噁心了。
不過這個時候是必須要寫了。
先貼幾個鏈接:
http://www.notonlysuccess.com/index.php/plug_dp/
http://blog.csdn.net/jasonzhu8/article/details/5779518
就小小的總結一下,寫【......】的時候讓人感覺實在玩接水管遊戲,其實只要把各種狀態寫在紙上,細心一點,多寫幾遍之後就沒那麼噁心了。
利用4進制,0表示無括號,1表示左括號,2表示右括號,爲了防止寫錯,就寫了兩個過程,get(state, p)和cor(state,p,alt),分別是詢問state的第p位 / 把state的第p位染成alt,這樣每次轉移時只用這兩個過程,就是的對於一遇到很多運算套在一起就暈(比如我)是一個很大的幫助,雖然會增加代碼量,但是爲了寫對還是值得的。
主要就是要注意細節,換行時的轉移,障礙的轉移,hash表的處理,只要細節處理好了,就基本上差不多了。
雖然不好調,但是模塊化應該還是沒有問題的。
ural1519:
模板題,曼哈頓迴路個數。
# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <ctime>
using namespace std;
const int S = 15000;
typedef long long int64;
struct HashMap
{
int top, linke[S*10], next[S*10], point[S*10];
int link(int x, int y)
{
++top; next[top] = linke[x]; linke[x] = top; point[top] = y;
return top;
}
int ask(int state)
{
int ke, hs = state % 10009;
for (ke = linke[hs]; ke; ke = next[ke])
if (point[ke] == state) break;
return ke? ke: link(hs, state);
}
}hash;
int n, m, head[2], tail[2], que[2][S*10], p;
int64 ans, f[2][S*10];
int mat[30], bct[30];
int lastn, lastm;
char c[30][30];
bool step[S*10];
inline int get(int state, int pl)
{
return (state>>((pl-1)<<1))&3;
}
inline void cor(int &state, int p, int alt)
{
int pri = get(state, p);
state ^= pri << ((p-1)<<1);
state |= alt << ((p-1)<<1);
}
void update(int SX, int x, int y)
{
f[p][x] += f[!p][y];
if (!step[x]) que[p][++tail[p]] = SX,step[x]=true;
}
void expand(int state, int line, int list)
{
//printf("%d\n", state);
int i,aim, X, Y, Z, pX, pY;
pX = list+1; pY = list+2;
X = get(state, pX); Y = get(state, pY);
if (c[line][list]=='*'&&(X!=0||get(state,list)!=0)) return;
if (list == m)
{
if (!X) update(state<<2, hash.ask(state<<2),hash.ask(state));
}
else if (c[line][list+1] == '*')
{
if ((!X)&&(!Y))
update(state, hash.ask(state),hash.ask(state));
}
else if ((!X) && (!Y))
{
aim = state; cor(aim, pX, 1);
cor(aim, pY, 2);
update(aim, hash.ask(aim),hash.ask(state));
}
else if ((!X)||(!Y))
{
update(state, hash.ask(state), hash.ask(state));
aim = state; cor(aim, pX, 0);
cor(aim, pY, 0);
cor(aim, pX, Y);
cor(aim, pY, X);
update(aim, hash.ask(aim),hash.ask(state));
}
else if (X==2 && Y==1)
{
aim = state; cor(aim, pX, 0);
cor(aim, pY, 0);
update(aim, hash.ask(aim),hash.ask(state));
}
else if (X==Y)
{
memset(mat,0,sizeof(mat));
memset(bct,0,sizeof(bct));
for (i = 1; i <= m+1; i++)
{
Z = get(state, i);
if (Z==1) mat[++mat[0]] = i;
else if (Z==2) bct[i] = mat[mat[0]], bct[mat[mat[0]--]] = i;
}
aim = state; cor(aim, pX, 0); cor(aim, pY, 0);
if (X==1) cor(aim, bct[pY], 1), update(aim, hash.ask(aim),hash.ask(state));
if (X==2) cor(aim, bct[pX], 2), update(aim, hash.ask(aim),hash.ask(state));
}
else if (lastn == line && lastm-1 == list)
{
aim = state; cor(aim, pX, 0); cor(aim, pY, 0);
if (!aim)ans += f[!p][hash.ask(state)];
}
}
void work()
{
int i, j;
que[1][head[1] = tail[1] = 1] = 0; p = 1;
f[1][hash.ask(0)] = 1;
for (i = 1; i <= n; i++)
for (j = 0; j <= m; j++)
{
p ^= 1;
memset(f[p], 0, sizeof(f[p])); head[p] = 1; tail[p] = 0;
memset(step, false, sizeof(step));
for (;head[!p] <= tail[!p]; head[!p]++)
expand(que[!p][head[!p]], i, j);
if (i == lastn && j == lastm) return;
}
}
int main()
{
int i, j;
freopen("ural1519.in", "r", stdin);
freopen("ural1519.out", "w", stdout);
scanf("%d%d\n", &n, &m);
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
scanf("%c", &c[i][j]);
if (c[i][j] == '.') lastn = i, lastm = j;
}
scanf("\n");
}
work();
//printf("%d\n", hash.top);
printf("%I64d", ans);
return 0;
}
poj1379:
有限制的曼哈頓路徑數量。
僅僅只是對上面的程序改了一點點。
# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <ctime>
using namespace std;
const int S = 1000;
typedef long long int64;
int linke[S], next[S], point[S];
int bct[20], que[2][S], head[2], tail[2], mat[20];
int64 ans, f[2][S];
int n, m, lastn, lastm, X, Y, pX, pY, p;
bool step[S];
char c[20][20];
int top;
inline int link(int x, int y)
{
++top; next[top] = linke[x]; linke[x] = top; point[top] = y;
return top;
}
inline int ask(int state)
{
int ke , hs = state % 997;
for (ke = linke[hs]; ke; ke = next[ke])
if (point[ke] == state) break;
return ke? ke:link(hs, state);
}
inline int get(int state, int pl)
{
return (state>>((pl-1)<<1))&3;
}
inline void cor(int &state, int p, int alt)
{
int tp = get(state, p);
state ^= tp << ((p-1)<<1);
state ^= alt << ((p-1)<<1);
}
inline void update(int state, int x, int y)
{
f[p][x] += f[!p][y];
if (!step[x]) que[p][++tail[p]] = state, step[x] = true;
}
void expand(int state, int line , int list)
{
int aim, i, pX = list+1, pY = list+2, X = get(state, pX), Y = get(state, pY);
if (list == m)
{
if (!X) update(state<<2, ask(state<<2), ask(state));
}
else if (c[line][list+1] == '#')
{
if ((!X)&&(!Y)) update(state, ask(state), ask(state));
}
else if ((!X)&&(!Y))
{
aim = state; cor(aim, pX, 1); cor(aim, pY, 2);
update(aim, ask(aim), ask(state));
}
else if ((!X)||(!Y))
{
aim = state; update(aim, ask(aim), ask(state));
cor(aim, pX, 0); cor(aim, pY, 0);
cor(aim, pX, Y); cor(aim, pY, X);
update(aim, ask(aim), ask(state));
}
else if (X==2&&Y==1)
{
aim = state;
cor (aim, pX, 0); cor(aim, pY, 0);
update(aim, ask(aim), ask(state));
}
else if (X==Y)
{
aim = state; memset(bct,0,sizeof(bct)); memset(mat,0,sizeof(mat));
for (i = 1; i <= m+1; i++)
{
int z = get(state, i);
if (z == 1) mat[++mat[0]] = i;
else if (z== 2) bct[i] = mat[mat[0]], bct[mat[mat[0]--]] = i;
}
cor(aim, pX, 0); cor(aim, pY, 0);
if (X==1) cor(aim, bct[pY], 1), update(aim, ask(aim), ask(state));
if (X==2) cor(aim, bct[pX], 2), update(aim, ask(aim), ask(state));
}
else if (line == lastn && list == lastm-1)
{
aim = state; cor(aim, pX, 0); cor(aim, pY, 0);
if (!aim) ans += f[!p][ask(state)];
}
}
void origin()
{
memset(c, sizeof(c), 0);
memset(linke, 0, sizeof(linke));
memset(point, 0, sizeof(point));
memset(next, 0, sizeof(next));
top = 0; ans =0; memset(f, 0, sizeof(f));
}
void work()
{
int i, j;
int aim = 0; cor(aim, 2, 1); cor(aim, m+1, 2);
p = 1; que[p][head[1]=tail[1]=1] = aim; f[p][ask(aim)] = 1;
for (i = 1; i <= n; i++)
for (j = 0; j <= m; j++)
{
if (i == lastn&& j == lastm) return;
p^=1;
memset(f[p], 0, sizeof(f[p]));
memset(step, 0, sizeof(step));
head[p] = 1;tail[p] = 0;
for (;head[!p]<=tail[!p];head[!p]++)
expand(que[!p][head[!p]], i, j);
}
}
int main()
{
int i, j;
//freopen("1739.in", "r", stdin);
//freopen("1739.out", "w", stdout);
for (;;)
{
origin();
scanf("%d%d\n", &n, &m);
if ((!n)&&(!m)) return 0;
for (i = n; i >= 1; i--)
{
for (j = 1; j <= m; j++)
scanf("%c", &c[i][j]);
scanf("\n");
}
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
if (c[i][j]=='.') lastn = i, lastm = j;
work();
// printf("%d\n", top);
if (c[1][1] == '#' || c[1][m] == '#') printf("0\n");
else printf("%I64d\n", ans);
}
return 0;
}
zoj3256
上題 + 矩乘
每次先用按格轉移的方式預處理出行與行之間的轉移,然後用矩乘優化。
寫的很醜很醜。。。。。。在zoj上tle了。。。。。。
# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <ctime>
using namespace std;
typedef long long int64;
const int mo = 7777777, S = 580;
int tot, n, m, p;
int bct[30], mat[30], head[2], tail[2], que[2][S+10];
int top, next[S+10], linke[S+10], point[S+10];
int64 f[2][S*5], g[180][180], mtx[180][180], tmp[180][180];
bool step[S*5];
inline int get(int state, int p)
{
return (state>>((p-1)<<1))&3;
}
inline void cor(int &state, int p, int alt)
{
int pri = get(state, p);
state ^= pri<<((p-1)<<1);
state |= alt<<((p-1)<<1);
}
inline int link(int x, int y)
{
++top; next[top] = linke[x]; linke[x] = top; point[top] = y;
//if (top > 200) exit(0);
return top;
}
inline int ask(int state)
{
int ke,hs = state % 173;
for (ke = linke[hs]; ke ; ke = next[ke])
if (point[ke] == state) break;
return ke?ke:link(hs, state);
}
inline bool check(int state)
{
int i, bt = 0, Z;
for (i = 1; i <= n; i++)
{
Z = get(state, i);
if (Z == 1) bt++;
else if (Z == 2) bt--;
if (bt<0) return false;
}
return bt?false:true;
}
inline void update(int st, int x, int y)
{
int Dx = ask(x);int Dy = ask(y);
f[p][Dx] += f[!p][Dy];
if (step[Dx]!=st) step[Dx] = st, que[p][++tail[p]] = x;
}
void expand(int st, int state, int list)
{
int i, aim, pX = list+1, pY = list+2, X = get(state, pX), Y = get(state, pY);
if (list == n-1 && X == 1 && Y == 2)
{
aim = state; cor(aim, pX, 0); cor(aim, pY, 0);
if (!aim) update(st, aim, state);
}
else if ((!X)&&(!Y))
{
aim = state; cor(aim, pX, 1); cor(aim, pY, 2);
update(st, aim, state);
}
else if ((!X)||(!Y))
{
aim = state; update(st, aim, state);
cor(aim, pX, Y); cor(aim, pY, X);
update(st, aim, state);
}
else if (X == 2&& Y == 1)
{
aim = state;
cor(aim, pX, 0); cor(aim, pY, 0);
update(st, aim, state);
}
else if (X == Y)
{
aim = state; cor(aim, pX, 0); cor(aim, pY, 0);
memset(bct, 0, sizeof(bct)); memset(mat, 0, sizeof(mat));
for (i = 1; i <= n+1; i++)
{
int Z = get(state, i);
if (Z == 1) mat[++mat[0]] = i;
else if (Z == 2) bct[i] = mat[mat[0]], bct[mat[mat[0]--]] = i;
}
if (X == 1) cor(aim, bct[pY], 1), update(st, aim, state);
if (X == 2) cor(aim, bct[pX], 2), update(st, aim, state);
}
}
void work(int state)
{
int i;
p = 1;head[p] = tail[p] = 1; que[1][1] = state;
memset(f, 0, sizeof(f)); f[p][ask(state)] = 1;
for (i = 0; i < n; i++)
{
p ^= 1; head[p] = 1; tail[p] = 0;
memset(f[p], 0, sizeof(f[p]));
memset(step, false, sizeof(step));
for (;head[!p]<= tail[!p];head[!p]++)
if (que[!p][head[!p]]!=0) expand(state,que[!p][head[!p]], i);
}
for (;head[p] <= tail[p];head[p]++)
if (get(que[p][head[p]], n+1)==0)
mtx[ask(state)][ask(que[p][head[p]]<<2)] += f[p][ask(que[p][head[p]])];
}
void dfs(int p, int state)
{
if (p == 0) {if (check(state)&&(state!=0)) work(state<<2)/*, printf("%d\n", state)*/; return;}
dfs(p-1, state<<2);
dfs(p-1, (state<<2)+1);
dfs(p-1, (state<<2)+2);
}
void dfsp(int p, int state)
{
if (p == 0)
{
if (check(state))
ask(state<<2);
return;
};
dfsp(p-1, state<<2);
dfsp(p-1, (state<<2)+1);
dfsp(p-1, (state<<2)+2);
}
void mul(int64 c[180][180], int64 a[180][180], int64 b[180][180])
{
int i, j, k;
memset(tmp, 0, sizeof(tmp));
for (i = 1; i <= tot; i++)
for (j = 1; j <= tot; j++)
for (k = 1; k <= tot; k++)
tmp[i][j] = (tmp[i][j] + a[i][k]*b[k][j]) % mo;
for (i = 1; i <= tot; i++)
for (j = 1; j <= tot; j++)
c[i][j] = tmp[i][j];
}
void origin()
{
top = 0; memset(next, 0, sizeof(next));
memset(linke, 0, sizeof(linke));
memset(point, 0, sizeof(point));
memset(g, 0, sizeof(g));
memset(mtx, 0, sizeof(mtx));
}
int main()
{
int i, j;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
while (scanf("%d%d", &n, &m)!=EOF)
{
origin();
dfsp(n,0);
tot = top;
dfs(n,0);
for (i = 1; i <= tot; i++)
for (j = 1; j <= tot; j++)
g[i][j] = mtx[i][j];
for (m--; m > 0; m>>=1, mul(mtx, mtx, mtx))
if (m&1) mul(g, g, mtx);
int aim = 0; cor(aim, 2, 1); cor(aim, n+1, 2);
int64 ans = g[ask(aim)][ask(0)];
if (ans) printf("%I64d\n", ans);
else printf("Impossible\n");
}
return 0;
}