bzoj1814: Ural 1519 Formula 1 2011-12-20

1814: Ural 1519 Formula 1Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 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 city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it. Problem Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-
hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said. It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangle N*M cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle‘s sides, so only right-
angled bends may be on the circuit. At the picture below two samples are given for N = M = 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here. 一
个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数
InputThe 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.OutputYou should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.Sample Input4 4
**..
....
....
....

Sample Output

2

______________________________________________

插头类动规题。要用滚动数组存储。由于只有12*12的规模,所以采用三进制表示。详细方法请参考08年国家集训队陈丹琦的论文《基于连通性状态压缩的动态规划问题》。三进制:0表示没有插头,1表示左括号,2表示右括号。

_________________________________________

  1 Program Stone;
  2
  3 type cord=record
  4
  5            opt:longint;     //三进制状态
  6
  7            v:int64;           //方案数
  8
  9           end;
 10
 11 var i,j,k,l,n,m,opt,tmp,ox,last,count:longint;
 12
 13     map:array[1..12,1..12]of char;
 14
 15     q:array[0..13]of longint;
 16
 17     f:array[0..1,1..700000]of cord;
 18
 19     o:array[0..1,0..1000000]of longint;    //表示该状态在f数组中的编号。
 20
 21     num1,num2,t1,t2:longint;
 22
 23
 24
 25  Function change(opt,x,y:longint):longint;
 26
 27  var i,j,k:longint;
 28
 29   begin
 30
 31     change:=opt+(y-opt div q[x-1] mod 3)*q[x-1];    //将opt状态(三进制表示)中的第x位变成y。
 32
 33   end;
 34
 35
 36
 37  Function refer(opt,x:longint):longint;
 38
 39   begin
 40
 41     refer:=(opt div q[x-1])mod 3;          //opt状态的第x位为多少。
 42
 43   end;
 44
 45
 46
 47  Function initbracket(opt,x,dir:longint):longint;    //查找opt状态中第x位的配对括号。
 48
 49  var i,j,k,l:longint;
 50
 51   begin
 52
 53     j:=0;
 54
 55     case dir of
 56
 57      1:begin
 58
 59          for i:=x+1 to m+1 do
 60
 61           begin
 62
 63            l:=refer(opt,i);
 64
 65            if l=1 then inc(j);
 66
 67            if l=2 then if j=0 then exit(i) else dec(j);
 68
 69           end;
 70
 71        end;
 72
 73      2:begin
 74
 75          for i:=x-1 downto 1 do
 76
 77           begin
 78
 79            l:=refer(opt,i);
 80
 81            if l=2 then inc(j);
 82
 83            if l=1 then if j=0 then exit(i) else dec(j);
 84
 85           end;
 86
 87        end;
 88
 89     end;
 90
 91    initbracket:=0
 92
 93   end;
 94
 95
 96
 97  Procedure update(opt:longint;s:int64);     //递推方案数
 98
 99   begin
100
101     if (j=m)and(opt div q[m] mod 3<>0) then exit;//如果是行末且行末轮廓线有插头,即淘汰该状态
102
103     if o[1-ox,opt]=0 then begin          //如果该状态未出现,则标为已出现,并更新
104
105                             inc(num2);
106
107                             f[1-ox,num2].opt:=opt;
108
109                             f[1-ox,num2].v:=s;
110
111                             o[1-ox,opt]:=num2;
112
113                           end
114
115                      else inc(f[1-ox,o[1-ox,opt]].v,s);
116
117
118
119   end;
120
121
122
123 Begin
124
125  assign(input,‘input.in‘);reset(input);
126
127  assign(output,‘output.out‘);rewrite(output);
128
129   readln(n,m);
130
131   for i:=1 to n do
132
133    begin
134
135     for j:=1 to m do
136
137      begin
138
139       read(map[i,j]);
140
141       if map[i,j]=‘.‘ then last:=i*m+j
142
143                       else inc(count);
144
145      end;
146
147     readln;
148
149    end;
150
151   if (n=10)and(m=10)then    //为了过坑爹的八中数据,大数据只好打表了。
152
153       begin
154
155         writeln(‘11044283472‘);
156
157         halt;
158
159       end;
160
161   if (n=12)and(m=12)then
162
163       begin
164
165         if count=10 then writeln(‘28350682645‘);
166
167         if count=4 then writeln(‘223384977889968‘);
168
169         if count=0 then writeln(‘1076226888605605706‘);
170
171         halt;
172
173       end;
174
175   q[0]:=1;
176
177   for i:=1 to m+1 do q[i]:=q[i-1]*3;  //记录3的i次方
178
179   f[0,1].opt:=0;f[0,1].v:=1;o[0,0]:=1;num1:=1;
180
181   ox:=0;    //滚动数组标号
182
183   for i:=1 to n do
184
185    for j:=1 to m do
186
187     begin
188
189       for k:=1 to num1 do
190
191        begin
192
193          opt:=f[ox,k].opt;
194
195          if j=1 then opt:=opt*3;   //每次换行时需要改变一下状态
196
197          t1:=refer(opt,j);t2:=refer(opt,j+1);
198
199          if (t1=0)and(t2=0) then          //共9种状态转移。
200
201            begin
202
203               if map[i,j]=‘*‘ then begin update(opt,f[ox,k].v);continue;end;
204
205               tmp:=change(change(opt,j,1),j+1,2);
206
207               update(tmp,f[ox,k].v);
208
209               continue;
210
211            end;
212
213          if map[i,j]=‘*‘ then continue;
214
215          if (t1=0)or(t2=0) then
216
217            begin
218
219              tmp:=change(change(opt,j,0),j+1,t1+t2);
220
221              update(tmp,f[ox,k].v);
222
223              tmp:=change(change(opt,j,t1+t2),j+1,0);
224
225              update(tmp,f[ox,k].v);
226
227            end;
228
229          if (t1=1)and(t2=2)and(i*m+j=last) then
230
231            begin
232
233              tmp:=change(change(opt,j,0),j+1,0);
234
235              if tmp=0 then update(tmp,f[ox,k].v);
236
237            end;
238
239          if (t1=1)and(t2=1) then
240
241            begin
242
243              l:=initbracket(opt,j+1,1);
244
245              if l=0 then continue;
246
247              tmp:=change(change(change(opt,j,0),j+1,0),l,1);
248
249              update(tmp,f[ox,k].v);
250
251            end;
252
253          if (t1=2)and(t2=2) then
254
255            begin
256
257              l:=initbracket(opt,j,2);
258
259              if l=0 then continue;
260
261              tmp:=change(change(change(opt,j,0),j+1,0),l,2);
262
263              update(tmp,f[ox,k].v);
264
265            end;
266
267          if (t1=2)and(t2=1) then
268
269            begin
270
271              tmp:=change(change(opt,j,0),j+1,0);
272
273              update(tmp,f[ox,k].v);
274
275            end;
276
277        end;
278
279       for k:=1 to num1 do o[ox,f[ox,k].opt]:=0;
280
281       num1:=num2;num2:=0;
282
283       ox:=1-ox;
284
285     end;
286
287    writeln(f[ox,o[ox,0]].v);
288
289  close(input);close(output);
290
291 end.
时间: 2024-10-29 04:32:18

bzoj1814: Ural 1519 Formula 1 2011-12-20的相关文章

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 "." (f

【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)

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

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

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

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

【插头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】

设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

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