poj 1739 Tony's Tour 插头dp

来源:互联网 发布:js点击文字展开省略 编辑:程序博客网 时间:2024/06/08 00:17

题目:http://poj.org/problem?id=1739

POJ 1739

题目大意:给一个最大8*8的会有一些地方不能走的图,指定左下角(N,1)为起点,右下角(N,M)为终点,求哈密尔顿链路的个数。



首先,我们要先看cdq的论文。

在看过以后,我有一个疑惑,就是关于修改括号的。

虽然很多人都会,但是我就是没看懂,Oct_gap说论文里有,但是我没领悟到。

cdq论文的case2里有一个,就是当左边和上面插头一样且不为0时,要修改插头。

我在此wa了无限次,不管有没有人和我一样,我都要写出来!

如何修改插头,首先,如果两个插头都是左插头,那么就往右边搜索,找到第一个没有匹配的右插头,改成左插头。

如果两个都是右插头,那么就往左边找,第一个没匹配的左插头,改为右插头。

具体实现:(都为左插头)

s:=1;

for i:=j+2(就是这俩插头个后面那个格子) to m+1 do

  begin

     if c[i]=1 then s:=s+1;

     if c[i]=2 then s:=s-1;

     if s=0 then begin  c[i]:=1 break; end;

  end;

这个问题如果理解错了,主要表现为:数据大时,结果会比答案少一点点!

排除了这个问题,我们可以起点和终点视为联通的,答案是左下角是左插头,右下角是右插头,其余为0的情况!

其他和cdq论文是一样的(其实这全部都一样,只是那个问题我没懂)

最后附上代码:(的notepad++里打的,那里面缩进都是正常的,在这缩进什么的就无视好了)

type  arr=array[0..12] of longint;var  fuck,sum,n,m,i,j,k,l,t:longint;  c,h:arr;  f:array[0..10,0..10,0..20000] of longint;  s:string;  g:array[0..10,0..10] of longint;procedure unzip(k:longint;var c:arr);  {把k解压成数组c}  var i:longint;  begin    for i:=m+1 downto 1 do begin c[i]:=k mod 3;k:=k div 3; end;  end;procedure zip(c:arr;i,j,k:longint);  {把c压缩成k 并且更新}  var    t,l:longint;  begin    t:=0;for l:=1 to m+1 do t:=t*3+c[l];f[i,j,t]:=f[i,j,t]+k;  end;begin  readln(n,m);  while (n<>0) and (m<>0) do begin   fillchar(f,sizeof(f),0);fillchar(g,sizeof(g),0);  for i:=1 to n do beginreadln(s);for j:=1 to m do if s[j]='.' then g[i,j]:=1;  end;    h[1]:=1;  for i:=2 to 11 do     h[i]:=h[i-1]*3;  f[0,m,0]:=1;  for i:=1 to n do beginfor j:=0 to h[m+1]-1 do f[i,0,j]:=f[i-1,m,j*3];for j:=0 to m-1 do for k:=0 to h[m+2]-1 do   if f[i,j,k]>0 then  begin   unzip(k,c);   if g[i,j+1]=1 then  begin           if (c[j+1]=c[j+2]) and (c[j+1]=0) then {左 上 没有}     begin           c[j+1]:=1;c[j+2]:=2;zip(c,i,j+1,f[i,j,k]);       continue;         end;       if (c[j+1]=0) and (c[j+2]>0) then {上面有 左边没有} begin           f[i,j+1,k]:=f[i,j+1,k]+f[i,j,k];           c[j+1]:=c[j+2];c[j+2]:=0;zip(c,i,j+1,f[i,j,k]);       continue;         end;           if (c[j+1]>0) and (c[j+2]=0) then {上面没有 左边有}     begin           f[i,j+1,k]:=f[i,j+1,k]+f[i,j,k];           c[j+2]:=c[j+1];c[j+1]:=0;zip(c,i,j+1,f[i,j,k]);       continue;         end;if (c[j+1]=2) and (c[j+2]=1) then {左边是右插头 上面是左插头} beginc[j+1]:=0;c[j+2]:=0;zip(c,i,j+1,f[i,j,k]);continue;end;       if (c[j+1]=c[j+2]) then {两边插头一样 不为0}     begin           if c[j+1]=1 then      begin   fuck:=1;           for l:=j+3 to m+1 do              begin   if c[l]=2 then fuck:=fuck-1;if c[l]=1 then fuck:=fuck+1;if fuck=0 then              begin                c[l]:=1;       break;             end;     end;         end   else begin   fuck:=1;           for l:=j downto 1 do              begin   if c[l]=1 then fuck:=fuck-1;if c[l]=2 then fuck:=fuck+1;               if fuck=0 then  begin        c[l]:=2;               break;          end; end; end;       c[j+1]:=0;c[j+2]:=0;   zip(c,i,j+1,f[i,j,k]);     end;     end   else  if (c[j+1]=0) and (c[j+2]=0) then f[i,j+1,k]:=f[i,j,k]+f[i,j+1,k];{图中点为#时}     end;  end;  fillchar(c,sizeof(c),0);t:=0;c[1]:=1;c[m]:=2;  for i:=1 to m+1 do    t:=t*3+c[i];  writeln(f[n,m,t]);  readln(n,m);  end;end.



下面是我错的数据:

6 6

#.....

......

......

..#...

......

......

86

错误答案:83


6 6

..#...

....#.

.#..#.

......

......

......

17

错误答案:15


6 6

......

.#....

.#....

......

......

......

120

错误答案:112


最后,感谢Oct_gap神犇帮我找出错误,我一定要争取国一!!

原创粉丝点击