模板—插头dp(Ural 1519 Formula 1)
括号表示法:
据说比下一个要快而且灵活。
- #include<iostream>
- #include<cstring>
- #include<cstdio>
- #define LL long long
- #define MAXN 20000
- #define HASH 23333
- #define ma(x,y) memset(x,y,sizeof(x))
- using namespace std;
- struct Hash_map
- {
- int size,first[HASH],next[MAXN];
- #define f(x) first[x]
- #define n(x) next[x]
- LL sta[MAXN],sum[MAXN];
- void init(){size=;ma(first,-);ma(sum,);}
- void push(LL states,LL Sum)
- {
- int pos=(states%HASH+HASH)%HASH;
- for(int i=f(pos);i>=;i=n(i))
- if(sta[i]==states){sum[i]+=Sum;return;}
- sta[size]=states;
- sum[size]=Sum;
- n(size)=f(pos);f(pos)=size++;
- }
- }dp[];
- int n,m,map[][],bin[],fx,fy;//最后一个可行点坐标
- int now,pre;
- int mov[]={,,,,,,,,,,,,};
- inline int getbit(LL st,int k){return (st>>mov[k])&;}//第k位状态
- inline int pybit(LL st,int k){return st<<mov[k];}//平移k位
- inline LL clrbit(LL st,int i,int j){return st&(~(<<mov[i]))&(~(<<mov[j]));}//清空i,j位
- inline int fl(LL st,int pos)//从左往右找和当前pos位置匹配的右括号
- {
- int cnt=;
- for(int i=pos+;i<=m;i++)
- {
- int k=getbit(st,i);
- if(k==)cnt++;
- else if(k==)cnt--;
- if(!cnt)return i;
- }
- }
- inline int fr(LL st,int pos)//从右往左找和当前pos位置匹配的左括号
- {
- int cnt=;
- for(int i=pos-;i>=;i--)
- {
- int k=getbit(st,i);
- if(k==)cnt--;
- else if(k==)cnt++;
- if(!cnt)return i;
- }
- }
- void DP(int x,int y,int k)
- {
- int l=getbit(dp[pre].sta[k],y-);
- int up=getbit(dp[pre].sta[k],y);
- LL st=clrbit(dp[pre].sta[k],y-,y);
- LL v=dp[pre].sum[k];
- if(!l&&!up)
- {
- if(!map[x][y]){dp[now].push(st,v);return;}
- if(x<n&&y<m&&map[x+][y]&&map[x][y+])
- dp[now].push(st|pybit(,y-)|pybit(,y),v);
- }
- else if(!l||!up)
- {
- int e=l+up;
- if(x<n&&map[x+][y])
- dp[now].push(st|pybit(e,y-),v);
- if(y<m&&map[x][y+])
- dp[now].push(st|pybit(e,y),v);
- }
- else if(l==&&up==)
- dp[now].push(st^pybit(,fl(st,y)),v);
- else if(l==&&up==)
- dp[now].push(st^pybit(,fr(st,y-)),v);
- else if(l==&&up==)
- dp[now].push(st,v);
- else if(x==fx&&y==fy)
- dp[now].push(st,v);
- }
- LL solve()
- {
- dp[].init();
- dp[].push(,);
- now=,pre=;
- for(int i=;i<=n;i++)
- {
- pre=now,now^=;dp[now].init();
- for(int k=;k<dp[pre].size;k++)
- dp[now].push(pybit(dp[pre].sta[k],),dp[pre].sum[k]);
- for(int j=;j<=m;j++)
- {
- pre=now,now^=;dp[now].init();
- for(int k=;k<dp[pre].size;k++)
- DP(i,j,k);
- }
- }
- for(int i=;i<dp[now].size;i++)
- if(dp[now].sta[i]==)
- return dp[now].sum[i];
- return ;
- }
- signed main()
- {
- // freopen("in.txt","r",stdin);
- bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]*;
- cin>>n>>m;char t;
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++)
- {
- cin>>t;
- if(t=='*')map[i][j]=;
- else map[i][j]=;
- }
- fx=;
- for(int i=n;i>&&!fx;i--)
- for(int j=m;j>&&!fx;j--)
- if(map[i][j])
- fx=i,fy=j;
- if(fx==)puts("");
- else cout<<solve()<<endl;
- }
括号表示法(这个是自己写的)
最小表示法(看不懂,下面是标程):
不过连我都能看出来它慢那它就是真的慢了。而且我也并没有觉得它好理解……
找到一个和自己码风相似的不容易啊……
- #include<bits/stdc++.h>
- #define LL long long
- using namespace std;
- const int maxn=,inc=,bit=;//3位二进制以及111的表示
- int n,m,now,pre,code[],bin[],res[];//用来表示状态的每一位的数值
- char gp[][],fx,fy;//图和最后的可行点
- struct node//离散化hash
- {
- int head[maxn],next[maxn],size;
- LL sum[maxn],sta[maxn];
- void clear()
- {
- memset(head,-,sizeof(head));
- size=;
- }
- void push(LL st,const LL v)
- {
- LL hash=st%maxn;
- for(int i=head[hash];i>=;i=next[i])
- {
- if(sta[i]==st)
- {
- sum[i]+=v;
- return ;
- }
- }
- sta[size]=st,sum[size]=v;
- next[size]=head[hash],head[hash]=size++;
- }
- }dp[];
- inline LL encode(int m)//将code转换成状态
- {
- LL st=;
- int cnt=;
- memset(bin,-,sizeof(bin));
- bin[]=;
- for(int i=m;i>=;i--)
- {
- if(bin[code[i]]==-)
- bin[code[i]]=cnt++;
- code[i]=bin[code[i]];
- st<<=inc;
- st|=code[i];
- }
- return st;
- }
- inline void decode(LL st,int m)//将状态转换成code
- {
- for(int i=;i<=m;i++)
- {
- code[i]=st&bit;
- st>>=inc;
- }
- }
- void DP(int x,int y,int k)//dp具体情况具体分析
- {
- decode(dp[pre].sta[k],m);
- int l=code[y-];
- int up=code[y];
- code[y-]=code[y]=;
- memcpy(res,code,sizeof(code));
- LL v=dp[pre].sum[k];
- if(!l&&!up)
- {
- if(gp[x][y]=='*')
- dp[now].push(encode(m),v);
- else if(x<n&&y<m&&gp[x+][y]=='.'&&gp[x][y+]=='.')
- {
- code[y]=code[y-]=bit;
- dp[now].push(encode(m),v);
- }
- }
- else if(!l||!up)
- {
- int e=l+up;
- if(x<n&&gp[x+][y]=='.')
- {
- code[y-]=e;
- dp[now].push(encode(m),v);
- memcpy(code,res,sizeof(res));
- }
- if(y<m&&gp[x][y+]=='.')
- {
- code[y]=e;
- dp[now].push(encode(m),v);
- }
- }
- else if(l!=up)
- {
- for(int i=;i<=m;i++)
- if(code[i]==up)
- code[i]=l;
- dp[now].push(encode(m),v);
- }
- else if(x==fx&&y==fy)
- dp[now].push(encode(m),v);
- }
- LL solve()
- {
- dp[].clear();//初始化状态
- dp[].push(,);
- now=,pre=;
- for(int i=;i<=n;i++)//逐格逐状态枚举转移
- {
- pre=now,now^=,dp[now].clear();
- for(int k=;k<dp[pre].size;k++)//轮廓线行转移
- dp[now].push(dp[pre].sta[k]<<inc,dp[pre].sum[k]);
- for(int j=;j<=m;j++)
- {
- pre=now,now^=,dp[now].clear();
- for(int k=;k<dp[pre].size;k++)
- {
- DP(i,j,k);
- }
- }
- }
- for(int i=;i<dp[now].size;i++)
- if(dp[now].sta[i]==)
- return dp[now].sum[i];
- return ;
- }
- int main()
- {
- while(~scanf("%d%d",&n,&m))
- {
- for(int i=;i<=n;i++)//都是从1开始
- scanf("%s",&gp[i][]);
- fx=fy=;
- for(int i=n;i>&&!fx;i--)//寻找最终的位置
- for(int j=m;j>&!fx;j--)
- if(gp[i][j]=='.')
- fx=i,fy=j;
- if(fx==)puts("");
- else cout<<solve()<<endl;
- }
- }
最小表示法(摘自某大佬)
模板—插头dp(Ural 1519 Formula 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 ...
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
[BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...
- 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 ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
- Ural 1519 Formula 1 插头DP
这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...
- URAL 1519 Formula 1(插头DP,入门题)
Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...
- 插头DP讲解+[BZOJ1814]:Ural 1519 Formula 1(插头DP)
1.什么是插头$DP$? 插头$DP$是$CDQ$大佬在$2008$年的论文中提出的,是基于状压$D$P的一种更高级的$DP$多用于处理联通问题(路径问题,简单回路问题,多回路问题,广义回路问题,生成 ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
- Ural 1519. Formula 1 优美的插头DP
今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的, ...
随机推荐
- docker-4-Dockerfile配置文件详解
Dockerfile简单一点就是描述你这个镜像安装了哪些软件包,有哪些操作,创建了什么东西.有些人喜欢用 docker commit 命令去打包镜像,这样是不好的,首先commit出来的镜像比你使 ...
- Lab1 ex1 物理页内存分配算法的实现
调用流程如下 kern_init --> pmm_init-->page_init-->init_memmap--> pmm_manager->init_memmap 从 ...
- Angungular.js 的过滤器&工具方法
字母大小写 数字 货币 截取字符串 截取数组 用JS操作 ----------------------------------------------------------------------- ...
- 洛谷P1313 [NOIP2011提高组Day2T1]计算系数
P1313 计算系数 题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别 ...
- POJ 1061 扩展欧几里得
#include<stdio.h> #include<string.h> typedef long long ll; void gcd(ll a,ll b,ll& d, ...
- Location 位置 history
拆分出来地址 让地址各归其位 search案例 查找历史记录跳转
- golang数据类型三
- cat、head、tail、more和less命令(文件内容浏览)
一.cat命令 cat命令连接文件并打印到标准输出设备上,cat经常用来显示文件的内容. 注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往往看不清所显示的内容.因此,一般用more等命令分屏显 ...
- mongoDB端口启动失败原因
删除以下文件: (所以数据会丢失,需要重新创建数据库)
- homework-//2017-12-27 11:11 星期三
//2017-12-27 11:11 星期三 const WEEKMAP = { 0:"sunday", 1:"monday", 2:"tuesday ...