bzoj1814: Ural 1519 Formula 1 动态规划 插头dp

dbzoj依然爆炸

题目描述

一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数。

输入

The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.

输出

You should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.

样例输入

4 4
**..
....
....
....

样例输出

2

dfs时间复杂度才能通过,我直接写了个dp里面有很多无用状态,改成dfs的就行了。。不想改了就先这样吧。

匹配就行了……没什么技术含量。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 using namespace std;
  8 #define LL long long
  9 int n,m;
 10 char ch[15][15]={};
 11 int id[15][15]={};
 12 LL shu[15]={};
 13 map< int,LL >f[200];
 14 inline int getit(int z,int i){return (z/shu[i])%3;}
 15 int main(){
 16     scanf("%d%d",&n,&m);
 17     for(int i=1;i<=n;i++)scanf("%s",ch[i]+1);
 18     for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=(i-1)*m+j;
 19     shu[1]=1;int ff=0;
 20     for(int i=2;i<=m+1;i++)shu[i]=shu[i-1]*3;
 21     if(ch[1][1]==‘.‘){f[1][1+2*3]=1;ff=1;}
 22     else f[1][0]=1;
 23     int mx=shu[m+1]*3,now,nex,fla,z,x,y; LL val;
 24     for(int i=1;i<=n;i++){
 25         for(int j=1;j<m;j++){
 26             if(i==n&&j==m-1)break;
 27             now=id[i][j];nex=now+1;fla=0;
 28             if(ch[i][j+1]!=‘.‘)fla=1;
 29             if(ch[i][j]==1)ff=1;
 30             for(int w=ff;w<mx;w++){
 31                 val=f[now][w];
 32                 if(val==0)continue;
 33                 x=getit(w,j+1);y=getit(w,j+2);
 34                 if(fla){
 35                     if(x==0&&y==0){
 36                         z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2];
 37                         f[nex][z]+=val;
 38                     }
 39                     continue;
 40                 }
 41                 if(x==0&&y==0){
 42                     z=w+(1-x)*shu[j+1]+(2-y)*shu[j+2];
 43                     f[nex][z]+=val;
 44                 }
 45                 else if(x==0||y==0){
 46                     z=w+(x+y-x)*shu[j+1]+(0-y)*shu[j+2];
 47                     f[nex][z]+=val;
 48                     z=w+(0-x)*shu[j+1]+(x+y-y)*shu[j+2];
 49                     f[nex][z]+=val;
 50                 }
 51                 else if(x==y){
 52                     z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2];
 53                     int zz,zzz;
 54                     if(x==1){
 55                         zz=-1;zzz=j+2;
 56                         while(zz!=0){
 57                             ++zzz;
 58                             if(zzz>m+1)break;
 59                             if(getit(w,zzz)==1)--zz;
 60                             if(getit(w,zzz)==2) ++zz;
 61                         }
 62                         if(zz!=0)continue;
 63                         z=z+(1-2)*shu[zzz];
 64                     }
 65                     else{
 66                         zz=1;zzz=j+1;
 67                         while(zz!=0){
 68                             --zzz;
 69                             if(zzz>m+1)break;
 70                             if(getit(w,zzz)==1)--zz;
 71                             if(getit(w,zzz)==2) ++zz;
 72                         }
 73                         if(zz!=0)continue;
 74                         z=z+(2-1)*shu[zzz];
 75                     }
 76                     f[nex][z]+=val;
 77                 }
 78                 else if(x==2&&y==1){
 79                     z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2];
 80                     f[nex][z]+=val;
 81                 }
 82             }
 83         }
 84         if(i==n)break;
 85         now=i*m;nex=now+1;
 86         fla=0;
 87         if(ch[i+1][1]!=‘.‘)fla=1;
 88         if(ch[i][m]==‘.‘)ff=1;
 89         for(int w=ff;w<mx;++w){
 90             val=f[now][w];
 91             if(val==0)continue;
 92             if(getit(w,m+1)!=0)continue;
 93             x=getit(w,1);
 94             if(fla){
 95                 if(!x){
 96                     z=(w%shu[m+1]-x)*3; f[nex][z]+=val;
 97                 }
 98                 continue;
 99             }
100             if(x==1){
101                 z=(w%shu[m+1]-x)*3;
102                 z=z+1;f[nex][z]+=val;
103                 z=z+2;f[nex][z]+=val;
104             }
105             else if(x==0){
106                 z=(w%shu[m+1]-x)*3+1+2*3;
107                 f[nex][z]+=val;
108             }
109         }
110     }
111     printf("%lld\n",f[n*m-1][shu[m]*1+shu[m+1]*2]);
112     return 0;
113 }

原文地址:https://www.cnblogs.com/137shoebills/p/8994374.html

时间: 2024-11-10 18:03:18

bzoj1814: Ural 1519 Formula 1 动态规划 插头dp的相关文章

URAL - 1519 Formula 1 (插头DP)

这里写链接内容 刚开始学插头dp好吃力,看了别人的代码有点看不懂,所以就参考了别人的代码,写了注释,希望有帮助 如果看不懂可以问 //下面所说的情况全在论文中的第13页 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 13 #define S1 14000 #define S2 1600000 struct Queue{ int opt; long

URAL 1519 Formula 1 (插头DP,常规)

题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的文章够详细,推荐一看(最好不要照抄代码). 细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等. 这次仍然用括号表示法,1表示(,2表示). 1 #include <bits/stdc++.h> 2 #define pii pair<int,int&g

bzoj 1814: Ural 1519 Formula 1【插头dp】

设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把它转到橙色轮廓线,设已经在状压的s中取到两条边的状态记为b1,b2 然后分很多情况讨论: (i,j)是障碍:那就只能什么都不放的转移,也就是只能从b1=0,b2=0转移到新轮廓线的b1=0,b2=0 if(!a[i][j]) { if(!b1&&!b2) add(x,v); } b1=0,b2

bzoj1814: Ural 1519 Formula 1 2011-12-20

1814: Ural 1519 Formula 1Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 263  Solved: 70[Submit][Status][Discuss]DescriptionRegardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well- known, that the 

【bzoj1814】Ural 1519 Formula 1 插头dp

题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. 输入 The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop)

【插头DP】URAL 1519 Formula 1

通道:http://acm.timus.ru/problem.aspx?space=1&num=1519 题意:单回路,经过全部可达点,有阻碍点. 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 13; const int MAX_M = 13; const int HASH = 10007; const in

bzoj 1814: Ural 1519 Formula 1 插头dp经典题

用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 199917 6 #define ll long long 7 #define bp 1<<bit[j-1] 8 #define bq 1<<bit[j] 9 using nam

[URAL 1519] Formula 1 轮廓线DP 括号序列

题意 n * m 的矩形, 有坏点, 问哈密顿回路数量. n, m <= 11 . 分析 1. 确立状态 我们考虑轮廓线DP. 为此, 我们要刻画并量化轮廓线的相关信息: ① 插头是否存在? ② 插头的连通性. 我们发现: 插头一一对应, 且互不相交. 于是考虑使用括号序列刻画轮廓线. 至于量化, 我们将一个括号序列当做一个三进制数即可. 2. 转移 从上一行的最后一个, 转移到当前行的第一个: 位移. 当前格子为坏点: 对于没有插头插到当前点的状态原样复制. 否则: (1) L = # , R

URAL 1519 Formula 1

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1519 陈丹琦的<基于连通性状态压缩的动态规划问题>的论文上的题目 题意: 给你m*n的棋盘,有的格子是障碍,问共有多少条回路使得经过每个非障碍格子恰好一次. 做法: 论文上的思路讲的很清楚了,这里用最小表示法来做. 因为(2 ≤ N, M ≤ 12),所以最多出现6个联通块,所以用8进制来做. 1 #include <bits/stdc++.h> 2 using name