ural 1519 Formula 1
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1519
题目分类:插头dp
题意:求经过所有可行点的哈密顿回路的个数 * 不可走 . 可以走 2 ≤ N, M ≤ 12
代码:
括号匹配法,转移有点复杂,但是时间空间比较小
#include<bits/stdc++.h> #define LL long long
using namespace std;
const int maxn=;
int n,m,now,pre;
int mov[]={,,,,,,,,,,,,};//根据进制选择移位距离
char gp[][],fx,fy;//存图,最后一个可行点的坐标
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位
struct node//状态离散hash
{
int head[maxn],next[maxn],size;
LL sum[maxn],sta[maxn];//保存所求和及状态
void clear()
{
memset(head,-,sizeof(head));
memset(sum,,sizeof(sum));
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 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(gp[x][y]=='*')
{
dp[now].push(st,v);
return;
}
if(x<n&&y<m&&gp[x+][y]=='.'&&gp[x][y+]=='.')
dp[now].push(st|pybit(,y-)|pybit(,y),v);
}
else if(!l||!up)
{
int e=l+up;
if(x<n&&gp[x+][y]=='.')
dp[now].push(st|pybit(e,y-),v);
if(y<m&&gp[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[].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(pybit(dp[pre].sta[k],),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=;
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;
}
return ;
}
最小表示法,转移简单,时间空间较大
#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;
}
}
ural 1519 Formula 1的更多相关文章
- 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 ...
- 【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板子题,刷板 ...
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 924 Solved: 351[Submit][Sta ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
- bzoj1814: Ural 1519 Formula 1 动态规划 插头dp
http://acm.timus.ru/problem.aspx?space=1&num=1519 题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. ...
- URAL 1519 Formula 1(插头DP,入门题)
Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...
- BZOJ1814: Ural 1519 Formula 1(插头Dp)
Description Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic gam ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
随机推荐
- 基于visual Studio2013解决C语言竞赛题之0904文件排序
题目
- docker 学习手冊-中文版下载
这个PDF算是学习docker的一个小总结,全部文章摘自我在csdn的博客专栏: http://blog.csdn.net/column/details/docker.html 第一章到第八章摘自do ...
- mysql的用户管理(二)
与权限相关的表由于经常需要用到,所以mysql直接将这些表在mysql启动时写到了内存中,避免每次验证权限时再从磁盘写数据. 当以下条件发生时发refresh权限表信息到内存: 1.对帐户的更改时,如 ...
- last期末作业
功能:每人完成一个新闻发布系统,包括系统的前台访问和后台管理. 要求: 1.使用ASP.NET MVC4开发. 2.在完成基本功能后,可以利用本学期所学的知识进行扩展. 3.完成日期为2013年12月 ...
- 在Windows下搭建C++11 编译环境(附下载,包括mingw-build,TDM-GCC, nuwen MinGW Distro)
由于现实的一些原因,并不是所有人都能很方便的享受到C++11 特性.特别是C++ Primer 第五版 和 The C++ Programming Language 第四版等全面C++ 11 铺开以后 ...
- Tomcat 7最大并发连接数的正确修改方法(转)
几乎所有的中文网页都介绍,要修改Tomcat的默认最大并发连接数,应该进行如下设置(实际上这些步骤是错误的): -------------------------------------------- ...
- Android UI 之WaterFall瀑布流效果
所谓瀑布流效果,简单说就是宽度相同但是高度不同的一大堆图片,分成几列,然后像水流一样向下排列,并随着用户的上下滑动自动加载更多的图片内容. 语言描述比较抽象,具体效果看下面的截图: ...
- 程序实践系列(七)C++概述
理论练习题 C++语言与C语言的本质区别是什么? [參考答案]:C++与C语言的本质区别就在于C++是面向对象的.而C语言是面向过程的. 面向过程的程序设计方法与面向对象的程序设计方法在对待数据和函数 ...
- 【linux】内核+文件系统下载到开发板
K开发 欢迎转载,转载时请保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:htt ...
- Delphi - SEH研究
技术交流,DH讲解. 前几天一个朋友在弄游戏外挂想带NP调试,就像自己来捕获游戏的异常.好像就要用到SEH这方面的知识.一起研究了一下,这里看下研究 和 在网上找的资料吧.SEH就是Structure ...