【矩阵优化连通性状压dp】哈密尔顿路径
2012-03-10 14:54
148 查看
以前觉得插头dp好晕啊,结果稍微推了一下转移发现并不难推,只是转移多了点罢了,可是noip模拟的时候270行的恶心转移dp都打过,100+的状压也就还好了。
本题有一维特别大,于是我们压缩小的那一维,然后裸转一行后,用矩阵加速即可。
转移第一次写会觉得麻烦,最后自己推一边在跟别人推的对一下检查有没有漏转或多转,至于要一模一样则没必要,我完全是按自己的喜好来的。
ural有道题是有障碍的哈密尔顿回路,可以拿来练手,注意答案要在最后一个非障碍点统计。
状态比较难记,所以用了hash,也方便预处理
ural1519
方便玩水管的程序,与我的程序配套,最高位为第一位
本题有一维特别大,于是我们压缩小的那一维,然后裸转一行后,用矩阵加速即可。
转移第一次写会觉得麻烦,最后自己推一边在跟别人推的对一下检查有没有漏转或多转,至于要一模一样则没必要,我完全是按自己的喜好来的。
ural有道题是有障碍的哈密尔顿回路,可以拿来练手,注意答案要在最后一个非障碍点统计。
状态比较难记,所以用了hash,也方便预处理
#include <cstdio> #include <cstdlib> #include <cstring> const int mo=1000003,nno=7777777; struct jz {int w[150][150];} f; int n,m,ss,s1,r,ans; int next[mo+mo],w[mo+mo],id[mo+mo],st[2000],net[2000][20],prim[50],ts[50]; inline int hash(int s) { int h=s%mo,r,i,ne; for (;next[h]!=0;) { h=next[h]; if (w[h]==s) return id[h]; } ss++,next[h]=ss,w[ss]=s,id[ss]=++s1; for (r=0,i=1;s;i++,s>>=2) { ne=s&3; if (2==ne) ts[++r]=i; else if (1==ne) net[s1][ts[r]]=i,net[s1][i]=ts[r],r--; } return s1; } inline void swap(int &ne,int ns,int yy) { int a=(ns>>yy)&3,b=(ns>>yy-2)&3; ne=(ns & prim[(yy>>1)]) & prim[(yy>>1)-1]; ne=(ne | (b<<yy)) | (a<<yy-2); } inline void replace(int lo,int &ne,int a) { lo=(lo-1)<<1; ne=ne & prim[lo>>1]; ne=ne | (a<<lo); } inline void dfs2(int x,int s,int ns) { int nv,v,yy,ne; if (x==n) { ns>>=2;nv=hash(ns);v=hash(s); f.w[v][nv]+=1; return ; } yy=(n-x)<<1; if ((0==((ns>>yy)&3))&&(0==((ns>>yy-2)&3))) { if (x==n-1) return ; ne=(ns | (1<<yy)) | (2<<yy-2); dfs2(x+1,s,ne); } else if ((0==((ns>>yy)&3))||(0==((ns>>yy-2)&3))) { if (0==((ns>>yy-2)&3)) { if (x!=n-1) swap(ne,ns,yy),dfs2(x+1,s,ne); dfs2(x+1,s,ns); } else { swap(ne,ns,yy),dfs2(x+1,s,ne); if (x!=n-1) dfs2(x+1,s,ns); } } else { ne=(ns & prim[yy>>1]) & (prim[(yy>>1)-1]); nv=hash(ns); if ((1==((ns>>yy)&3))&&(2==((ns>>yy-2)&3))) if ((!ne)&&(x==n-1)) dfs2(x+1,s,ne); if ((2==((ns>>yy)&3))&&(1==((ns>>yy-2)&3))) dfs2(x+1,s,ne); if ((1==((ns>>yy)&3))&&(1==((ns>>yy-2)&3))) replace(net[nv][(yy>>1)],ne,1),dfs2(x+1,s,ne); if ((2==((ns>>yy)&3))&&(2==((ns>>yy-2)&3))) replace(net[nv][(yy>>1)+1],ne,2),dfs2(x+1,s,ne); } } inline void dfs(int x,int sum,int s) { int ns; if (sum<0) return ; if (x>n+1) { if (0==sum) st[++r]=s,hash(s);return ;} ns=(s<<2)+1,dfs(x+1,sum+1,ns); ns=(s<<2)+2,dfs(x+1,sum-1,ns); ns=(s<<2),dfs(x+1,sum,ns); } void origin() { int i,j; r=0; dfs(2,0,0); prim[0]=((1<<31)-1)-3; for (i=1;i<=10;i++) { prim[i]=1; for (j=i*2+2;j<=25;j++) prim[i]=(prim[i]<<1)+1; prim[i]<<=2; for (j=1;j<=i*2;j++) prim[i]=(prim[i]<<1)+1; } } inline void mul(jz &a,jz x,jz y) { int i,j,k; memset(a.w,0,sizeof(a.w)); for (i=1;i<=r;i++) for (j=1;j<=r;j++) for (k=1;k<=r;k++) a.w[i][j]=(a.w[i][j]+(long long)x.w[i][k]*y.w[k][j])%nno; } void fgm(jz &f,jz b,int e) { for (e-=1;e;e>>=1) { if (1==(e&1)) mul(f,f,b); mul(b,b,b); } } void init() { int i,s,j; scanf("%d%d\n",&n,&m); ss=mo,s1=0; origin(); for (i=1;i<=r;i++) if (st[i]!=0) dfs2(0,st[i],st[i]); fgm(f,f,m); s=(1<<((n-1)*2)),s+=2; i=hash(s),j=hash(0); ans=f.w[i][j]; printf("%d\n",ans); } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); init(); return 0; }
ural1519
#include <cstdio> #include <cstdlib> #include <cstring> const int mo=1000003,mt=150000; bool a[30][30]; int v[mt],u,e,n,m,st[2][mt],r[2],next[3000000],id[3000000],w[3000000],ss,s1,ts[100],net[mt][50],prim[50]; long long f[2][mt],ans; void change(int i,int nv,int ns) { if (!v[nv]) v[nv]=++r[u],st[u][r[u]]=ns,f[u][v[nv]]=0; f[u][v[nv]]+=f[e][i]; } int hash(int s) { int h,r,i,ne; h=s%mo; for (;next[h]!=0;) { h=next[h]; if (w[h]==s) return id[h]; } ss++,next[h]=ss,id[ss]=++s1,w[ss]=s; for (i=1,r=0;s;s>>=2,i++) { ne=s&3; if (2==ne) ts[++r]=i; else if (1==ne) net[s1][i]=ts[r],net[s1][ts[r]]=i,r--; } return s1; } void swap(int yy,int s,int &ns) { int na=(s>>yy)&3,ne=(s>>(yy-2))&3; ns=(s&prim[yy>>1])&(prim[(yy>>1)-1]); ns=ns | (ne<<yy) | (na<<(yy-2)); } void replace(int lo,int &ns,int na) { lo=lo-1; ns=(ns&prim[lo]) | (na<<(lo<<1)); } void updata(int i,int x,int y) { int yy=(m-y)<<1,s=st[e][i],s1=hash(s),nv,ns; if ((0==((s>>yy)&3))&&(0==((s>>(yy-2))&3))) { if (!a[x][y+1]) {nv=hash(s),change(i,nv,s);return ; } if ((a[x+1][y+1])&&(a[x][y+2])) { ns=(s | (1<<yy)) | (2<<(yy-2));nv=hash(ns); change(i,nv,ns); } } else if ((0==((s>>yy)&3))||(0==((s>>(yy-2))&3))) { if (!a[x][y+1]) return ; if (0==((s>>(yy-2))&3)) { if (a[x][y+2]) swap(yy,s,ns),nv=hash(ns),change(i,nv,ns); if (a[x+1][y+1]) nv=hash(s),change(i,nv,s); } else { if (a[x+1][y+1]) swap(yy,s,ns),nv=hash(ns),change(i,nv,ns); if (a[x][y+2]) nv=hash(s),change(i,nv,s); } } else if (!((1==((s>>yy)&3))&&(2==((s>>(yy-2))&3)))) { if (!a[x][y+1]) return ; ns=(s&prim[yy>>1])&(prim[(yy>>1)-1]); if (((1==((s>>yy)&3))&&(1==((s>>(yy-2))&3)))) { replace(net[s1][(yy>>1)],ns,1); nv=hash(ns); change(i,nv,ns); } else if ((2==((s>>yy)&3))&&(2==((s>>(yy-2))&3))) { replace(net[s1][(yy>>1)+1],ns,2); nv=hash(ns); change(i,nv,ns); } else nv=hash(ns),change(i,nv,ns); } } void origin() { int i,j; prim[0]=((1<<31)-1)-3; for (i=1;i<=14;i++) { j=i,prim[i]=1; for (j=i*2+3;j<=31;j++) prim[i]=(prim[i]<<1)+1; prim[i]<<=2; for (j=1;j<=i*2;j++) prim[i]=(prim[i]<<1)+1; } } void init() { int i,j,x,y,s,yy,la,lb; char ch; scanf("%d%d\n",&n,&m); memset(a,0,sizeof(a)); for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { scanf("%c",&ch); if ('*'==ch) a[i][j]=0;else a[i][j]=1,la=i,lb=j; } scanf("\n"); } origin(); ss=mo,s1=0; st[e=0][r[e]=1]=0,f[e][1]=1; x=1,y=0; for (;(x!=la)||(y!=lb);e=u) { memset(v,0,sizeof(v)); u=e^1,r[u]=0; if (y==m) { for (i=1;i<=r[e];i++) st[u][++r[u]]=st[e][i]>>2,f[u][r[u]]=f[e][i]; y=0,x++; } else { for (i=1;i<=r[e];i++) updata(i,x,y);y++; } // for (i=1;i<=r[e];i++) printf("%d ",st[e][i]);printf("\n"); } ans=0,u=e^1; for (i=1;i<=r[u];i++) { s=st[u][i],yy=(m-lb)<<1; if ((((s>>yy)&3)==2)&&(((s>>yy+2)&3)==1)) ans+=f[u][i]; } printf("%I64d\n",ans); } int main() { freopen("ural1519.in","r",stdin); freopen("ural1519.out","w",stdout); init(); return 0; }
方便玩水管的程序,与我的程序配套,最高位为第一位
# include <cstdlib> # include <cstdio> # include <cmath> # include <cstring> using namespace std; int main() { int tmp, m, d, g[20]; int stop = 0; printf("len=?\n"); scanf("%d", &m);m++; printf("询问吧,我的主人~.~\n"); while( stop < 1000 ) { memset(g, 0, sizeof(g)); scanf("%d", &d); stop++; printf("%d的四进制为: ", d) ; for (int i = 1;i <= m;i++, d/= 4) g[++g[0]] = d%4; for (int i = 1;i*2 <= m; i++) tmp = g[i], g[i] = g[m-i+1], g[m-i+1] = tmp; for (int i = 1; i <= m; i++) printf("%d", g[i]); printf("\n"); printf("括号序列:"); for (int i = 1; i <= g[0]; i++) if (g[i] == 0) printf("*"); else if (g[i] == 1) printf("("); else printf(")"); printf("\n"); } return 0; }
相关文章推荐
- hdu-2157-How many ways?? (矩阵)(dp优化加速)
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
- hdu5318 The Goddess Of The Moon (矩阵高速幂优化dp)
- loj#2325. 「清华集训 2017」小 Y 和恐怖的奴隶主 (矩阵快速幂优化概率dp)
- Poj 3734 Blocks(DP,矩阵乘法优化)
- bzoj 1009&&1875[矩阵优化dp]
- poj3744(矩阵优化 概率dp)
- 【Contra】 矩阵乘法优化 dp
- hdu 3962(AC自动机+矩阵优化dp)
- 1009: [HNOI2008]GT考试 矩阵乘法优化DP+KMP
- hdu 5564 Clarke and digits 矩阵快速幂优化数位dp
- poj 3744 矩阵优化的概率DP
- [BZOJ4861][BJOI2017]魔法咒语(AC自动机+矩阵优化DP)
- [矩阵快速幂 优化DP] 51Nod 1311 转换机
- Codeforces #341 E. Wet Shark and Blocks dp 矩阵优化
- BZOJ 1875 SDOI 2009 HH去散步 矩阵乘法优化DP
- 玲珑杯 1009 Spoon Devil's Bucket 矩阵优化DP
- hdu 4576(简单概率dp | 矩阵优化)
- BZOJ 1875 [SDOI 2009] HH去散步 (DP,矩阵乘法优化)
- 【DP】在矩阵中,选择一条从左上角到右下角、经过数字之和最大的路径