【矩阵优化连通性状压dp】哈密尔顿路径
来源:互联网 发布:mac怎么新建html文件 编辑:程序博客网 时间:2024/04/29 06:26
以前觉得插头dp好晕啊,结果稍微推了一下转移发现并不难推,只是转移多了点罢了,可是noip模拟的时候270行的恶心转移dp都打过,100+的状压也就还好了。
本题有一维特别大,于是我们压缩小的那一维,然后裸转一行后,用矩阵加速即可。
转移第一次写会觉得麻烦,最后自己推一边在跟别人推的对一下检查有没有漏转或多转,至于要一模一样则没必要,我完全是按自己的喜好来的。
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;}
- 【矩阵优化连通性状压dp】哈密尔顿路径
- 矩阵乘法优化DP
- 矩阵乘法优化DP
- poj3744(概率DP+矩阵优化)
- 【Contra】 矩阵乘法优化 dp
- 【HDU2294】Pendant-DP矩阵优化
- 地铁网络(分层图-哈密尔顿路径)
- 地铁网络(分层图-哈密尔顿路径)
- 从哈密尔顿路径谈NP问题
- 从哈密尔顿路径谈NP问题
- poj1651矩阵连乘(DP)+路径
- 矩阵的最小路径和 [DP]
- 程序碎片- 矩阵乘法优化(dp,递归)
- 程序碎片- 矩阵乘法优化(dp,循环)
- hdu 2294 Pendant DP+矩阵优化
- 3734 Blocks DP矩阵优化入门
- bzoj1009 GT考试 KMP+矩阵优化DP
- BNUOJ 34985 Elegant String DP+矩阵优化
- 求助安装linux系统
- 记录远程登录地址批处理
- Apache Nutch 1.3 学习笔记一
- .NET Framework 数据提供程序
- Google AdMob Ads iOS Fundamentals
- 【矩阵优化连通性状压dp】哈密尔顿路径
- css常用设置
- hdu3779---记忆化搜索
- 1.获取文件夹中文件信息原来如此容易
- poj1012
- db2 的缓冲池设计
- 对于document.createElement 创建 input 控件无法得到值问题
- J2SE代码例子收集(IO)二
- VC++工具栏按钮手动添加响应函数