【基于联通性的状态压缩动态规划】

  


      以前一直被【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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值