楼教主男人八题之一。。。

题目大意:

求从左下角经过所有非障碍点一次到达右下角的方案数

这里不是求回路,但是我们可以考虑,在最下面一行再增加一行,那么就可以当做求此时左下角到右下角的回路总数,那么就转化成了陈丹琦论文的URAL1519的

方法了

但是最后一行添加的格子必须是最后一条直线跑的,也就是除了左下角和右下角中间的点只能有水平方向上的插头

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
#define ll long long
const int HASH = ;
const int STATE = ;
const int MAXD = ;
int n , m , enx , eny;
int code[MAXD] , mp[MAXD][MAXD];
bool flag[MAXD][MAXD];//标记位,标记当前点能否作为最终点
ll ans = ;
struct HASHMAP{
int head[HASH] , next[STATE] , state[STATE] , size;
ll f[STATE]; void init(){
size = ;
memset(head , - , sizeof(head));
} void push_in(int st , ll sum){
int h = st%HASH;
for(int i = head[h] ; ~i ; i=next[i]){
if(st == state[i]){
f[i]+=sum;
return ;
}
}
f[size]=sum;
state[size] = st;
next[size] = head[h];
head[h] = size++;
}
}hashmap[]; int num = ;//记录共有的插头数量
void decode(int *code , int m , int st)
{
num = ;
for(int i=m ; i>= ; i--){
code[i] = st&;
st>>=;
if(code[i]) num++;
}
} int encode(int *code , int m)
{
int st=;
for(int i= ; i<=m ; i++){
st<<=;
st |= code[i];
}
return st;
} void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
{
for(int i=m ; i>= ; i--) code[i] = code[i-];
code[] = ;
} void dpblank(int i , int j , int cur)
{
int k , left , up;
for(k= ; k<hashmap[cur].size ; k++){
decode(code , m , hashmap[cur].state[k]);
left = code[j-];
up = code[j];
// cout<<"chatou: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl;
if(!left && !up){
if(mp[i][j+] && mp[i-][j]){ //不断向上转移
code[j-] = , code[j] = ;
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
else if(!left && up){
if(mp[i][j+]) hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
if(mp[i-][j]){
code[j-] = up , code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
else if(left && !up){
if(mp[i-][j]){
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
if(mp[i][j+]){
code[j-] = , code[j] = left;
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
else if(left== && up == ){
int cnt = ;
for(int v=j+ ; v<=m ; v++){
if(code[v]==)cnt++;
if(code[v]==)cnt--;
if(!cnt){
code[v]=;
break;
}
}
code[j-] = code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
else if(left == && up == ){
int cnt=;
for(int v=j- ; v>= ; v--){
if(code[v]==)cnt++;
if(code[v]==)cnt--;
if(!cnt){
code[v]=;
break;
}
}
code[j-] = code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
else if(left== && up==){
if(i==enx && j==eny) {
code[j-] = code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
else{
code[j-]=code[j]=;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
} void dpblock(int i , int j , int cur)
{
int k , left , up;
for(k= ; k<hashmap[cur].size ; k++){
decode(code , m , hashmap[cur].state[k]);
left = code[j-];
up = code[j];
// cout<<"block: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl;
if(!left && !up){
if(j==m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]); }
}
} void dpselect(int i , int j , int cur)
{
int k , left , up;
for(k= ; k<hashmap[cur].size ; k++){
decode(code , m , hashmap[cur].state[k]);
left = code[j-];
up = code[j];
if(left== && !up){
code[j-] = , code[j] = ;
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
} char s[MAXD][MAXD]; void init()
{
for(int i= ; i<=n ; i++){
scanf("%s" , s[i]+);
for(int j= ; j<=m ; j++){
mp[i][j] = s[i][j]=='.';
}
}
for(int i=n ; i>= ; i--)
for(int j= ; j<=m ; j++)
if(mp[i][j]) enx=i , eny=j;
mp[n+][] = , mp[n+][m] = ;
for(int i= ; i<m ; i++) mp[n+][i] = ;
n++;
for(int i= ; i<=m+ ; i++) mp[][i] = ;
for(int i= ; i<=n ; i++) mp[i][m+] = ;
/* for(int i=0 ; i<=n ; i++)
{
for(int j=1 ; j<=m+1 ; j++){
cout<<mp[i][j]<<" ";
}
cout<<endl;
}
cout<<enx<<" "<<eny<<endl;*/
} ll solve()
{
ans = ;
int cur = ;
hashmap[cur].init();
hashmap[cur].push_in( , );
for(int i=n ; i>= ; i--){
for(int j= ; j<=m ; j++){
hashmap[cur^].init();
if(mp[i][j]==) dpblank(i , j , cur);
else if(mp[i][j]==) dpblock(i , j , cur);
else dpselect(i , j , cur);
cur^=;
} }
for(int i= ; i<hashmap[cur].size ; i++) ans+=hashmap[cur].f[i];
return ans;
} int main()
{
// freopen("in.txt" , "r" , stdin);
int cas = ;
while(scanf("%d%d" , &n , &m) , n+m)
{
init();
// printf("Case %d: ",++cas);
if(n== && m==){
printf("%d\n" , );
continue;
}
printf("%I64d\n" , solve());
}
return ;
}

POJ 1739的更多相关文章

  1. [POJ 1739] Tony's Tour

    Link: POJ 1739 传送门 Solution: 这题除了一开始的预处理,基本上就是插头$dp$的模板题了 由于插头$dp$求的是$Hamilton$回路,而此题有起点和终点的限制 于是可以构 ...

  2. POJ 1739:Tony's Tour

    Description A square township has been divided up into n*m(n rows and m columns) square plots (1< ...

  3. POJ 1739 Tony's Tour (DP)

    题意:从左下角到右下角有多少种走法. 析:特殊处理左下角和右下角即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000 ...

  4. POJ 1739 Tony's Tour(插头DP)

    Description A square township has been divided up into n*m(n rows and m columns) square plots (1< ...

  5. POJ 1739 Tony's Tour (插头DP,轮廓线DP)

    题意:给一个n*m的矩阵,其中#是障碍格子,其他则是必走的格子,问从左下角的格子走到右下角的格子有多少种方式. 思路: 注意有可能答案是0,就是障碍格子阻挡住了去路. 插头DP有两种比较常见的表示连通 ...

  6. 【POJ】【1739】Tony's Tour

    插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可 ...

  7. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  8. 【HDOJ】【2829】Lawrence

    DP/四边形不等式 做过POJ 1739 邮局那道题后就很容易写出动规方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}(表示前 j 个点分成 i 块的最小代价) $w(l, ...

  9. 插头DP题目泛做(为了对应WYD的课件)

    题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. #inc ...

随机推荐

  1. HTTP Status 500 - An exception occurred processing at line 35

    HTTP Status 500 - An exception occurred processing JSP page /manage/addCategory.jsp at line 35 type ...

  2. er6855的工作经验

    1 VIEWS里面的关系要搞清楚 里面的内容类型要理清 不要相信别人做好的事情 不要相信看到的结果 2 git rm -rf之后需要git commit提交到.git文件中正式生效 不然可能就是中间打 ...

  3. mysql+tomcat+spring 配置心得(从0开始搭环境)

    前几天公司竞一个标要做个POC,前端AugularJs做mobile界面,后端Spring MVC做Restful API供前端调用. 时间紧急,大家都忙,so我这个不写代码的闲人花一上午配了一套Sp ...

  4. js封装,一个JS文件引用多个JS文件

    (function() { //加载   varobj =  {};   /**    * 动态加载脚本函数    * @param url 要加载的脚本路径    * @param callback ...

  5. 如何增加Asp.Net Core生成的模板网站中用户信息表中的列(AspNetUsers)

    环境: 1.VS2015 Community 14.0.25431.01 Update 3; 2.其他环境(具体哪一个影响不太清楚,都列在这儿) 使用的系统模板 利用系统提供的模板,并选择个人身份验证 ...

  6. 使用PowerShell简化我的工作

    欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...

  7. 字符串(string)转json

    第一种方式: 使用js函数eval(); testJson=eval(testJson);是错误的转换方式. 正确的转换方式需要加(): testJson = eval("(" + ...

  8. Laravel 实现定时任务

    运行命令schedule run 时laravel会去App\console\kernel.php文件中查找schedule方法,有没有要执行的定时命令 实现流程:首先可以自定义命令并注册命令(参考上 ...

  9. (08)odoo继承机制

    * 全局的引用    所有的的模型定义外,都在注册中心注册了,我们可以用全局变量来引用这些模型    self.env[mode name] 比如得到合作伙伴这个模型 self.evn['res.pa ...

  10. JavaScript实现数组转置

    //数组转置  var  arr=[[2,5,6,8],[8,5,6,9],[9,6,2,1]] ;   var arrNew=[];//定义一个新数组   for(var i=0;i<arr[ ...