括号表示法:

据说比下一个要快而且灵活。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #define LL long long
  5. #define MAXN 20000
  6. #define HASH 23333
  7. #define ma(x,y) memset(x,y,sizeof(x))
  8. using namespace std;
  9. struct Hash_map
  10. {
  11. int size,first[HASH],next[MAXN];
  12. #define f(x) first[x]
  13. #define n(x) next[x]
  14. LL sta[MAXN],sum[MAXN];
  15. void init(){size=;ma(first,-);ma(sum,);}
  16. void push(LL states,LL Sum)
  17. {
  18. int pos=(states%HASH+HASH)%HASH;
  19. for(int i=f(pos);i>=;i=n(i))
  20. if(sta[i]==states){sum[i]+=Sum;return;}
  21. sta[size]=states;
  22. sum[size]=Sum;
  23. n(size)=f(pos);f(pos)=size++;
  24. }
  25. }dp[];
  26. int n,m,map[][],bin[],fx,fy;//最后一个可行点坐标
  27. int now,pre;
  28. int mov[]={,,,,,,,,,,,,};
  29. inline int getbit(LL st,int k){return (st>>mov[k])&;}//第k位状态
  30. inline int pybit(LL st,int k){return st<<mov[k];}//平移k位
  31. inline LL clrbit(LL st,int i,int j){return st&(~(<<mov[i]))&(~(<<mov[j]));}//清空i,j位
  32. inline int fl(LL st,int pos)//从左往右找和当前pos位置匹配的右括号
  33. {
  34. int cnt=;
  35. for(int i=pos+;i<=m;i++)
  36. {
  37. int k=getbit(st,i);
  38. if(k==)cnt++;
  39. else if(k==)cnt--;
  40. if(!cnt)return i;
  41. }
  42. }
  43. inline int fr(LL st,int pos)//从右往左找和当前pos位置匹配的左括号
  44. {
  45. int cnt=;
  46. for(int i=pos-;i>=;i--)
  47. {
  48. int k=getbit(st,i);
  49. if(k==)cnt--;
  50. else if(k==)cnt++;
  51. if(!cnt)return i;
  52. }
  53. }
  54. void DP(int x,int y,int k)
  55. {
  56. int l=getbit(dp[pre].sta[k],y-);
  57. int up=getbit(dp[pre].sta[k],y);
  58. LL st=clrbit(dp[pre].sta[k],y-,y);
  59. LL v=dp[pre].sum[k];
  60. if(!l&&!up)
  61. {
  62. if(!map[x][y]){dp[now].push(st,v);return;}
  63. if(x<n&&y<m&&map[x+][y]&&map[x][y+])
  64. dp[now].push(st|pybit(,y-)|pybit(,y),v);
  65. }
  66. else if(!l||!up)
  67. {
  68. int e=l+up;
  69. if(x<n&&map[x+][y])
  70. dp[now].push(st|pybit(e,y-),v);
  71. if(y<m&&map[x][y+])
  72. dp[now].push(st|pybit(e,y),v);
  73. }
  74. else if(l==&&up==)
  75. dp[now].push(st^pybit(,fl(st,y)),v);
  76. else if(l==&&up==)
  77. dp[now].push(st^pybit(,fr(st,y-)),v);
  78. else if(l==&&up==)
  79. dp[now].push(st,v);
  80. else if(x==fx&&y==fy)
  81. dp[now].push(st,v);
  82. }
  83. LL solve()
  84. {
  85. dp[].init();
  86. dp[].push(,);
  87. now=,pre=;
  88. for(int i=;i<=n;i++)
  89. {
  90. pre=now,now^=;dp[now].init();
  91. for(int k=;k<dp[pre].size;k++)
  92. dp[now].push(pybit(dp[pre].sta[k],),dp[pre].sum[k]);
  93. for(int j=;j<=m;j++)
  94. {
  95. pre=now,now^=;dp[now].init();
  96. for(int k=;k<dp[pre].size;k++)
  97. DP(i,j,k);
  98. }
  99. }
  100. for(int i=;i<dp[now].size;i++)
  101. if(dp[now].sta[i]==)
  102. return dp[now].sum[i];
  103. return ;
  104. }
  105. signed main()
  106. {
  107. // freopen("in.txt","r",stdin);
  108.  
  109. bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]*;
  110. cin>>n>>m;char t;
  111. for(int i=;i<=n;i++)
  112. for(int j=;j<=m;j++)
  113. {
  114. cin>>t;
  115. if(t=='*')map[i][j]=;
  116. else map[i][j]=;
  117. }
  118. fx=;
  119. for(int i=n;i>&&!fx;i--)
  120. for(int j=m;j>&&!fx;j--)
  121. if(map[i][j])
  122. fx=i,fy=j;
  123. if(fx==)puts("");
  124. else cout<<solve()<<endl;
  125. }

括号表示法(这个是自己写的)

最小表示法(看不懂,下面是标程):

不过连我都能看出来它慢那它就是真的慢了。而且我也并没有觉得它好理解……

找到一个和自己码风相似的不容易啊……

  1. #include<bits/stdc++.h>
  2.  
  3. #define LL long long
  4. using namespace std;
  5. const int maxn=,inc=,bit=;//3位二进制以及111的表示
  6. int n,m,now,pre,code[],bin[],res[];//用来表示状态的每一位的数值
  7. char gp[][],fx,fy;//图和最后的可行点
  8. struct node//离散化hash
  9. {
  10. int head[maxn],next[maxn],size;
  11. LL sum[maxn],sta[maxn];
  12. void clear()
  13. {
  14. memset(head,-,sizeof(head));
  15. size=;
  16. }
  17. void push(LL st,const LL v)
  18. {
  19. LL hash=st%maxn;
  20. for(int i=head[hash];i>=;i=next[i])
  21. {
  22. if(sta[i]==st)
  23. {
  24. sum[i]+=v;
  25. return ;
  26. }
  27. }
  28. sta[size]=st,sum[size]=v;
  29. next[size]=head[hash],head[hash]=size++;
  30. }
  31. }dp[];
  32. inline LL encode(int m)//将code转换成状态
  33. {
  34. LL st=;
  35. int cnt=;
  36. memset(bin,-,sizeof(bin));
  37. bin[]=;
  38. for(int i=m;i>=;i--)
  39. {
  40. if(bin[code[i]]==-)
  41. bin[code[i]]=cnt++;
  42. code[i]=bin[code[i]];
  43. st<<=inc;
  44. st|=code[i];
  45. }
  46. return st;
  47. }
  48. inline void decode(LL st,int m)//将状态转换成code
  49. {
  50. for(int i=;i<=m;i++)
  51. {
  52. code[i]=st&bit;
  53. st>>=inc;
  54. }
  55. }
  56. void DP(int x,int y,int k)//dp具体情况具体分析
  57. {
  58. decode(dp[pre].sta[k],m);
  59. int l=code[y-];
  60. int up=code[y];
  61. code[y-]=code[y]=;
  62. memcpy(res,code,sizeof(code));
  63. LL v=dp[pre].sum[k];
  64. if(!l&&!up)
  65. {
  66. if(gp[x][y]=='*')
  67. dp[now].push(encode(m),v);
  68. else if(x<n&&y<m&&gp[x+][y]=='.'&&gp[x][y+]=='.')
  69. {
  70. code[y]=code[y-]=bit;
  71. dp[now].push(encode(m),v);
  72. }
  73. }
  74. else if(!l||!up)
  75. {
  76. int e=l+up;
  77. if(x<n&&gp[x+][y]=='.')
  78. {
  79. code[y-]=e;
  80. dp[now].push(encode(m),v);
  81. memcpy(code,res,sizeof(res));
  82. }
  83. if(y<m&&gp[x][y+]=='.')
  84. {
  85. code[y]=e;
  86. dp[now].push(encode(m),v);
  87. }
  88. }
  89. else if(l!=up)
  90. {
  91. for(int i=;i<=m;i++)
  92. if(code[i]==up)
  93. code[i]=l;
  94. dp[now].push(encode(m),v);
  95. }
  96. else if(x==fx&&y==fy)
  97. dp[now].push(encode(m),v);
  98. }
  99. LL solve()
  100. {
  101. dp[].clear();//初始化状态
  102. dp[].push(,);
  103. now=,pre=;
  104. for(int i=;i<=n;i++)//逐格逐状态枚举转移
  105. {
  106. pre=now,now^=,dp[now].clear();
  107. for(int k=;k<dp[pre].size;k++)//轮廓线行转移
  108. dp[now].push(dp[pre].sta[k]<<inc,dp[pre].sum[k]);
  109. for(int j=;j<=m;j++)
  110. {
  111. pre=now,now^=,dp[now].clear();
  112. for(int k=;k<dp[pre].size;k++)
  113. {
  114. DP(i,j,k);
  115. }
  116. }
  117. }
  118. for(int i=;i<dp[now].size;i++)
  119. if(dp[now].sta[i]==)
  120. return dp[now].sum[i];
  121. return ;
  122. }
  123. int main()
  124. {
  125. while(~scanf("%d%d",&n,&m))
  126. {
  127. for(int i=;i<=n;i++)//都是从1开始
  128. scanf("%s",&gp[i][]);
  129. fx=fy=;
  130. for(int i=n;i>&&!fx;i--)//寻找最终的位置
  131. for(int j=m;j>&!fx;j--)
  132. if(gp[i][j]=='.')
  133. fx=i,fy=j;
  134. if(fx==)puts("");
  135. else cout<<solve()<<endl;
  136. }
  137. }

最小表示法(摘自某大佬)

模板—插头dp(Ural 1519 Formula 1)的更多相关文章

  1. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 924  Solved: 351[Submit][Sta ...

  2. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

  3. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  4. bzoj 1814 Ural 1519 Formula 1 插头DP

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 942  Solved: 356[Submit][Sta ...

  5. ural 1519 Formula 1(插头dp)

    1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...

  6. Ural 1519 Formula 1 插头DP

    这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...

  7. URAL 1519 Formula 1(插头DP,入门题)

    Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...

  8. 插头DP讲解+[BZOJ1814]:Ural 1519 Formula 1(插头DP)

    1.什么是插头$DP$? 插头$DP$是$CDQ$大佬在$2008$年的论文中提出的,是基于状压$D$P的一种更高级的$DP$多用于处理联通问题(路径问题,简单回路问题,多回路问题,广义回路问题,生成 ...

  9. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  10. Ural 1519. Formula 1 优美的插头DP

    今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的, ...

随机推荐

  1. docker-4-Dockerfile配置文件详解

    ​ Dockerfile简单一点就是描述你这个镜像安装了哪些软件包,有哪些操作,创建了什么东西.有些人喜欢用 docker commit 命令去打包镜像,这样是不好的,首先commit出来的镜像比你使 ...

  2. Lab1 ex1 物理页内存分配算法的实现

    调用流程如下 kern_init --> pmm_init-->page_init-->init_memmap--> pmm_manager->init_memmap 从 ...

  3. Angungular.js 的过滤器&工具方法

    字母大小写 数字 货币 截取字符串 截取数组 用JS操作 ----------------------------------------------------------------------- ...

  4. 洛谷P1313 [NOIP2011提高组Day2T1]计算系数

    P1313 计算系数 题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别 ...

  5. POJ 1061 扩展欧几里得

    #include<stdio.h> #include<string.h> typedef long long ll; void gcd(ll a,ll b,ll& d, ...

  6. Location 位置 history

    拆分出来地址  让地址各归其位 search案例 查找历史记录跳转

  7. golang数据类型三

  8. cat、head、tail、more和less命令(文件内容浏览)

    一.cat命令 cat命令连接文件并打印到标准输出设备上,cat经常用来显示文件的内容. 注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往往看不清所显示的内容.因此,一般用more等命令分屏显 ...

  9. mongoDB端口启动失败原因

    删除以下文件: (所以数据会丢失,需要重新创建数据库)

  10. homework-//2017-12-27 11:11 星期三

    //2017-12-27 11:11 星期三 const WEEKMAP = { 0:"sunday", 1:"monday", 2:"tuesday ...